问题:
给定一个数组a[0,…,n-1],数组元素有正有负,求其最大子数组(长度>=1)的和。
分析与解法:
如果不考虑时间复杂度,可以枚举出所有子数组并求和。但是由于长度为n的数组有O(n^2)个子数组;而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n^3)。
很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,否则这个负数将会减少接下来的和。所以解法可以是如果当前和为负数,那么就放弃前面的累加和,从数组中的下一个数再开始计数,时间复杂度为O(n)。
int sum(int a[], int n)
{
if(a != NULL && n != 0)
{
int i;
int cSum, eSum;//cSum是当前和,eSum是最终和
cSum = eSum = 0;
for(i = 0; i < n; i++)
{
cSum += a[i];
if(cSum < 0)//若cSum为负数,则清0
cSum = 0;
if(cSum > eSum)//若cSum的值大于eSum,则更新eSum
eSum = cSum;
}
//若eSum值为0,即数组元素全为负数,则需要找出数组中的最大负数
if(eSum == 0)
{
eSum = a[0];
for(i = 1; i < n; i++)
{
if(eSum < a[i])
eSum = a[i];
}
}
return eSum;
}
}
思考题:取出和最大的子数组