题目
输入要给整形数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。求所以子数组的和的最大值。要求时间复杂度为O(n)
例如输入数组为{1,-2,3,10,-4,7,2,-5}和最大的子数组为{3,10,-4,7,2},因此输出为该子数组的和为18
如果枚举数组中所有的子数组并求和。一个长度为n的数组,总共有n(n+1)/2个子数组。计算出所以子数组的和,最快也需要O(n2)时间
解法1:举例分析数组的规律
从头到尾诸葛累加示例数组中的每个数字,初始化为0。第一步加1,此时和为1,接下来第二不加上数字为-2,和就变成了-1,第三部加上数字3,我们注意到此时累计的和为-1,小于0,那如果-1加上3,得到和为2,比3小,也就是第一个数字开始的子数组的和会小于第三个数组开始的子数组的和,因此抛弃之前的累计
我们从第三个数字开始累加,此时和为3,接下来第四部家10,得到13,第五步加上-4,和为9,发现-4是个负数,因此累加到-4之后得到的和比原来的小,因此吧之前和为13的保存下来,有可能是最大的子数组的和,第六步加上数字7,9加上7为16,比之前13还大,更新最大值,此后加上2,为18,依次。。。。
boolean g_invalidInput=false;
int FindGreatestSumofSubArray(int[] pdata) {
if (pdata == null || pdata.length <= 0)
{
g_invalidInput=true;
return 0;
}
g_invalidInput=false;
int mCurSum=0;
int nGreatestSum=pdata[0];
for (int i=0;i<pdata.length;i++){
if (mCurSum<=0){
mCurSum=pdata[i];
}else {
mCurSum+=pdata[i];
}
if (mCurSum>nGreatestSum){
nGreatestSum=mCurSum;
}
}
return nGreatestSum;
}
解法2:应用动态规划
使用动态规划方法来实现:
如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max(f[0...n])。
我们可以给出如下递归公式求f(i)
|-- array[i] 如果i==0或者f(i-1)<0
f(i)= |
|-- f(i-1) + array[i] 如果f(i-1)>0
当以第(i-1)个数字为结尾的子数组中所有数字的和f(i-1)小于0时,如果把这个负数和第i个数相加,得到的结果反而不第i个数本身还要小,所以这种情况下最大子数组和是第i个数本身。
如果以第(i-1)个数字为结尾的子数组中所有数字的和f(i-1)大于0,与第i个数累加就得到了以第i个数结尾的子数组中所有数字的和。
虽然用递归去处理,但是最终都会用循环取编码,上述公式对应的代码和前面给的代码一致。