题目:给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [2,-3, 2,-1, 3],
输出: 4
解释: 连续子数组 [2,-1, 3] 的和最大,为 4。
进阶:
如果你已经实现复杂度为 O(n) 的解法(即动态规划法),尝试使用更为精妙的分治法求解。
在这里动态规划法对我来说是最不好理解的,所以着重讲一下这个方法。
核心在于找出子问题,所谓子问题,就是形式上与原问题一致,但是规模更小的问题。
首先,我们把原问题转化为一个等价的描述:
给定一个整数数组nums,长度为N。
设Fk为:以数列中第k项结尾的全部连续子数组中具有最大和的那一个子数组的和;
求F1,...,FN中的最大值。
/**************************************************************************************************/
具体地阐述一下Fk的含义,比如对于上面那个数组[2,-3, 2,-1, 3]:
当k=3时nums[3]==-1,那么以-1结尾的全部连续子数组包括:
[-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)+nums[k+1](说明此时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;