首页 > 代码库 > 动态规划解决“最大子数组”问题

动态规划解决“最大子数组”问题

TODO: 动态规划到底是个什么玩艺?

ref:http://www.cnblogs.com/waytofall/archive/2012/04/10/2439820.html

 

I 只考虑怎样产生更大的子组和:

假设处理到第i个节点时:

1. 考虑是否i节点是否可使子组的和变大

  a) 如果i节点大于0,则最大子组和是前面求到的数组和 加上 i节点值

      b) 如果i节点小于0(等于0的话,值可以带上i,也可以不带上i,无所谓),当最大子数组的和是前面求的子组和

2. 然后考虑最大值是否应该更新了

     a) 如果当前子组和大于最大和,则更新

int // 动态规划法
get_max_sub(int a[], int len)
{
    int max_sum, cur_sum;
    int i;

    max_sum = cur_sum = a[0];

    i = 0;
    while (++i < len) {
        if (cur_sum > 0) {
            cur_sum += a[i];
        } else {
            cur_sum = a[i];
        }

        if (cur_sum > max_sum) {
            max_sum = cur_sum;
        }
    }

    return max_sum;
}

 

 

II 再细化考虑子数组的前后边界

  1. 因为子数组和是负时,则最大值就是i节点,则将左边界挪到i节点上。

      2. 当i节点为负,(思维雷区!!),到于右边办什么时挪?当然是子数组和变大了再挪了(子和变大了,子数组扩张了)

int // 动态规划法
get_max_sub(int a[], int len, int &lt, int &rt)
{
    int max_sum, cur_sum;
    int i;

    max_sum = cur_sum = a[0];
    lt = rt = 0;

    i = 0;
    while (++i < len) {
        if (cur_sum > 0) {
            cur_sum += a[i];
        } else {
            cur_sum = a[i];
            lt = i;
        }

        if (cur_sum > max_sum) {
            max_sum = cur_sum;
            rt = i;
        }
    }

    return max_sum;
}

 

总结:

1. 思维深度一点点加深,由少及多

2. 摆脱思维惯性,避开雷区。

 

考虑最大子数组时,考虑的中心是历史子数组和是正还是负(即子数组和是当前第个i节点呢还是第i个节点加上以前的和呢),而不是只考虑加上i节点子数组是变大还是变小(直观/惯性思维引入雷区)

 

动态规划解决“最大子数组”问题