题目:输入一个整型数组,数组中有正数也有负数。数组中一个或连续多个整数组成一个子数组。求所有子数组的和的最大值,要为时间复杂度为O(n)。
可以这么想,假设这个数组的具有最大和的连续子数组区间为[x,y),该数组的中间元素的下标是mid。mid和[x,y)的关系又一下三种:
所以,对于前两种情况,由于mid并不包含在最大子数组里,所以可使left=x或right=y,然后递归求解。
对于第三种情况,可从mid分别向左和右遍历,找出边界下标。
代码如下:
int _FindMaxCrossSumArray(vector<int> v,int left,int mid,int right)
{
int LeftSum=-2147483647,RightSum=-2147483647;
int LeftPos,RightPos;
int Sum=0;
int i;
for(i=mid;i>=left;--i)
{
Sum+=v[i];
if(Sum>LeftSum)
{
LeftSum=Sum;
LeftPos=i;
}
}
Sum=0;
for(i=mid+1;i<=right;++i)
{
Sum+=v[i];
if(Sum>RightSum)
{
RightSum=Sum;
RightPos=i;
}
}
Sum=0;
for(i=LeftPos;i<=RightPos;++i)
{
Sum+=v[i];
}
return Sum;
}
int _FindGreatestSumOfSubArray(vector<int> v,int left,int right)
{
if(left>=right)
return v[left];
int mid=left+(right-left)/2;
int LeftSum=_FindGreatestSumOfSubArray(v,left,mid);
int RightSum=_FindGreatestSumOfSubArray(v,mid+1,right);
int MidSum=_FindMaxCrossSumArray(v,left,mid,right);
if(LeftSum>=RightSum && LeftSum>=MidSum)
return LeftSum;
else if(RightSum>=LeftSum && RightSum>=MidSum)
return RightSum;
else
return MidSum;
}
int FindGreatestSumOfSubArray(vector<int> v)
{
if(v.size()<=0)
throw new exception();
return _FindGreatestSumOfSubArray(v,0,v.size()-1);
}
以上
如果你有任何想法或是可以改进的地方,欢迎和我交流!
完整代码及测试用例在github上:点我前往