问题描述
给定一个有n(n≥1)个整数的序列,要求求出其中最大连续子序列的和。
例如:
序列(-2,11,-4,13,-5,-2)的最大子序列和为20
序列(-6,2,4,-7,5,3,2,-1,6,-9,10,-2)的最大子序列和为16。
规定一个序列最大连续子序列和至少是0(看成0个元素构成的子序列),如果小于0,其结果为0。
解法1
设含有n个整数的序列a[0…n-1],其中任何连续子序列a[i…j](i≤j,0≤i≤n-1,i≤j≤n-1)求出它的所有元素之和thisSum。
通过比较将最大值存放在maxSum中,最后返回maxSum。
int maxSubSum1(int a[], int n)
{
int i, j, k;
int maxSum = 0, thisSum;
for (i = 0; i < n; i++)
{
for (j = i; j < n; j++)
{
thisSum = 0;
for (k = i; k <= j; k++)
thisSum += a[k];
if (thisSum > maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
解法2
改进前面的解法,在求两个相邻子序列和时,它们之间是关联的。
例如a[0…3]子序列和=a[0]+a[1]+a[2]+a[3],a[0…4]子序列和=a[0]+a[1]+a[2]+a[3]+a[4],在前者计算出来后,求后者时只需在前者基础上加以a[4]即可,没有必须每次都重复计算。从而提高了算法效率。
int maxSubSum2(int a[], int n)
{
int i, j;
int maxSum = 0, thisSum;
for (i = 0; i < n; i++)
{
thisSum = 0;
for (j = i; j < n; j++)
{
thisSum += a[j];
if (thisSum > maxSum)
maxSum = thisSum;
}
}
return maxSum;
}
解法3
更一步改进解法2。
如果扫描中遇到负数,当前子序列和thisSum将会减小,若thisSum为负数,表明前面已经扫描的那个子序列可以抛弃了,则放弃这个子序列,重新开始下一个子序列的分析,并置thisSum为0。
若这个子序列和thisSum不断增加,那么最大子序列和maxSum也不断增加。
int maxSubSum3(int a[], int n)
{
int j, maxSum = 0, thisSum = 0;
for (j = 0; j < n; j++)
{
thisSum += a[j];
if (thisSum < 0)
thisSum = 0;
if (maxSum < thisSum)
maxSum = thisSum;
}
return maxSum;
}