求最大子序和的动态规划法(Leetcode第53题)

题目:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [2,-3, 2,-1, 3],
输出: 4
解释: 连续子数组 [2,-1, 3] 的和最大,为 4。

进阶:

如果你已经实现复杂度为 O(n) 的解法(即动态规划法),尝试使用更为精妙的分治法求解。

在这里动态规划法对我来说是最不好理解的,所以着重讲一下这个方法。

核心在于找出子问题,所谓子问题,就是形式上与原问题一致,但是规模更小的问题。

首先,我们把原问题转化为一个等价的描述

给定一个整数数组nums,长度为N。

设Fk为:以数列中第k项结尾的全部连续子数组中具有最大和的那一个子数组的和;

求F1,...,FN中的最大值。

/**************************************************************************************************/

具体地阐述一下Fk的含义,比如k=3时,nums[3]==-1,以4结尾的全部连续子数组包括:

-1; 和为-1

2 -1; 和为1

-3  2 -1; 和为-2

2 -3  2 -1; 和为0

具有最大和的数组为上述的第二个数组,那么F3等于1.

/**************************************************************************************************/

我们具体地看上面定义的这个新问题,按上述思路,数组2 -3  2 -1  3的F0→F4分别为:

F0:     2                                        F0= 2    是所有以2结尾的子数组中的具有最大和的那个子数组的和

F1:     2  -3                                   F1=-1   是所有以-3结尾的子数组中的具有最大和的那个子数组的和

F2:     _   _   2                              F2= 2    是所有以2结尾的子数组中的具有最大和的那个子数组的和

F3:     _   _   2   -1                        F3= 1   是所有以-1结尾的子数组中的具有最大和的那个子数组的和

F4:     _   _   2   -1   3                   F4= 4   是所有以3结尾的子数组中的具有最大和的那个子数组的和 

可以看到,F(k+1)要么等于F(k),要么等于F(k)加上nums[k+1]本身。

显然,这个新问题是与原问题等价的。因为在本质上我们已经遍历了所有可能的情况。

而对于Fk来讲,F1,...,Fk-1都是Fk的子问题:因为从k→1,问题的形式是相同的,但规模不断缩小。当k==1时,这就变成了一个平凡的问题。

用更专业的话术来讲,新问题Fk称为“状态”,从状态到状态之间,存在着状态转移方程:

F[i+1] = max(F[i]+nums[i+1],nums[i+1]),

化简之后,就是比较F[i] ?> 0 (F[i] + nums[i+1] ?> nums[i+1])。

//动态规划
int sum = 0, maxn = INT_MIN;
   for(int i=0; i<nums.size(); i++){
       if(sum >= 0)
           sum += nums[i];
       else
           sum = nums[i];
       if(sum > maxn)
           maxn = sum;
   }
   return maxn;

猜你喜欢

转载自blog.csdn.net/qq_41230365/article/details/81390805
今日推荐