题意:找到最大子数组的和。
分析:用分治法。假设把一个数组[low,high]分成两半[low,mid]和[mid,high],那么[low,high]的最大子序列之和只可能是以下三者中的最大值:
1、[low,mid]的最大子序列之和。
2、[mid+1,high]的最大子序列之和。
3、一个横跨[low,mid]和[mid+1,high]的最大子序列之和。
其中横跨[low,mid]和[mid,high]的最大子序列和可以在O(n)时间内计算出来。计算方法是:首先计算A[mid]+A[mid-1]+A[mid-2]+...+A[low],把计算过程中的和的最大值记下来,记为MaxSum1,MaxSum1就是从中间往左边扩展能得到的最大的和。然后计算A[mid+1]+A[mid+2]+...+A[high],把计算过程中的和的最大值记下来,记为MaxSum2,MaxSum2就是从中间往右边扩展能得到的最大的和。于是(MaxSum1+MaxSum2)就是横跨[low,mid]和[mid,high]的最大子序列之和。
这样就能使用分治法求解,并且T(n)=2T(n/2)+O(n),根据主定理得算法的时间复杂度是O(nlgn)。
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return maxSubArray(0,nums.size()-1,nums);
}
int maxSubArray(int low,int high,vector<int>& nums)
{
if(low==high) return nums[low];
int mid=(low+high)/2;
int leftMax=maxSubArray(low,mid,nums);
int rightMax=maxSubArray(mid+1,high,nums);
int sum=0,sumMax1=nums[mid],sumMax2=nums[mid+1];
for(int i=mid;i>=low;i--)
{
sum+=nums[i];
if(sum>=sumMax1) sumMax1=sum;
}
sum=0;
for(int i=mid+1;i<=high;i++)
{
sum+=nums[i];
if(sum>=sumMax2) sumMax2=sum;
}
return max(max(leftMax,rightMax),sumMax1+sumMax2);
}
};