求一个数组的最大和子串
思路:
(1)用两个游标i,j同时从前往后扫描,用preSum和postSum记录两个方向的前n向和;
(2)用两个固定的位置pos1,pos2记录对应子串的范围,即(pos1,pos2);
(3)若preSum<0,则重新把preSum置为0,pos1等于那个比较大的负数的位置;
(4)若postSum<0,则重新把postSum置为0,post2等于那个比较大的负数的位置;
(5)循环终止条件为i>=j,此时(pos1,pos2)即为和最大的子串。
int GetMaxSumSubArray(int a[], int length1)
{
int i = 0;
int pos1 = 0;
int j = length1 - 1;
int pos2 = length1 - 1;
int preSum = 0;
int postSum = 0;
while (i < length1)
{
if (i >= j)
{
for (int i = 0; i <= pos1; ++i)
{
a[i] = 0;
}
for (int j = pos2; j < length1;++j)
{
a[j] = 0;
}
break;
}
preSum += a[i];
postSum += a[j];
if (preSum < 0)
{
preSum = 0;
pos1 = i;
}
if (postSum < 0)
{
postSum = 0;
pos2 = j;
}
++i; --j;
}
return 0;
}
/*
最优方法,时间复杂度O(n)
和最大的子序列的第一个元素肯定是正数
因为元素有正有负,因此子序列的最大和一定大于0
*/
int MaxSubSum3(int *arr,int len)
{
int i;
int MaxSum = 0;
int CurSum = 0;
for(i=0;i<len;i++)
{
CurSum += arr[i];
if(CurSum > MaxSum)
MaxSum = CurSum;
//如果累加和出现小于0的情况,
//则和最大的子序列肯定不可能包含前面的元素,
//这时将累加和置0,从下个元素重新开始累加
if(CurSum < 0)
CurSum = 0;
}
return MaxSum;
}
没有考虑全部为负数的情况,输出结果如下: