题目:
输入一个整形数组,数据里有正数也有负数,数组中一个或连续的多个整数组成一个子数组。求所有子数组的和的最大值。要求时间复杂度为O(n)
例如输入数组{1,-2,3,10,-4,7,2,-5};
分析:
最简单的方法就是枚举每一种情况,当然这是不符合题意的,因为题目中要求时间复杂度是O(n),而如果枚举的话是O(n2)。
有两种理解方法来对应本题。
方法一:
首先我们可以遍历这个数组,一个个来。首先我们把sum=0;当进行到一个数时就加上此时sum = 1,然后第二个此时sum = -1.因为这个数是一个负数,就算后面的数再大,也不可能从它的基础上往后加了,所以我们抛弃这个数,接下来从3开始,sum=3;再往后sum=13,再往后sum=9,此时9小于13,我们保留之前的13它有可能是最大的(如果后面还有更大的数那么它就没有可能做老大了),再往后sum=16,它比13大,所以13就不要了,更新成了16,再往后sum=18,直到最后一个sum=13,因为没有18大,并且是最后一个数了,所以最后的答案是18.
依据咱们上面的过程就可以写出代码了:
int FindMaxSumOfSubArray(int *date,int length)
{
if(date == NULL || length < 0)
{
cout<<"空指针异常"<<endl;
return 0;
}
int sum =0;
int maxSum = 0;
for(int i=0;i<length;i++)
{
if(sum <= 0)
sum = date[i];
else
sum += date[i];
if(sum > maxSum )
maxSum = sum;
}
return maxSum;
}
方法二:
动态规划,这是最简单的一个动态规划的题目。
如果用函数f(i)表示第i个数字结尾的子数组的最大和,那么我们需要求出max f(i),就是我们要的结果,
f(i)={
data[i] i=0或者f(i-1)<=0
f(i-1)+data[i] i != 0或者f(i-1)>0
}
公式的意义:当以第i-1个数字结尾的子数组中所有数字的和小于0时,如果把这个负数与第i个数累加,得到的结果比第i个数字本身还要小,所以这种情况下以第i个数字结尾的子数组就是第i个 数字本身,如果以第i-1个数字结尾的子数组中所有数字的和大于0,与第i个数字累加就得到以第i个数字结尾的子数组中所有数字的和。
虽然思路不一样,但是所形成的代码是一样的