1.分治
分而治之,分数组为左半段与右半段,母数组的最大子序,可能藏在三个位置:
- 左半段,递归
- 右半段,递归
- 横跨左右半段分界点的一段,从分界点到左端点最大值+从分界点到右端点最大值
左端点为l,右端点为r,中点center = (l+r)/2,左半部分[l,center],右半部分[center+1,r]。
递归基:l==r,返回单点值。
T(N) = T(N/2) + O(N) — (1)
T(1) = O(1) — (2)
由(1)、(2)式推出T(N) = O(NLogN)
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return maxSubSum(nums,0,nums.size() - 1);
}
int maxSubSum( vector<int>& nums, int l, int r ){
int leftmax,rightmax,lefthalf,lefthalfmax,righthalf,righthalfmax,center;
if( l == r ){
return nums[l];
}
center = ( l + r ) / 2;
leftmax = maxSubSum(nums,l,center);
rightmax = maxSubSum(nums,center + 1, r);
lefthalf = 0;
lefthalfmax = INT_MIN;
for( int i = center; i >= l; i-- ){
lefthalf += nums[i];
lefthalfmax = lefthalf > lefthalfmax ? lefthalf : lefthalfmax;
}
righthalf = 0;
righthalfmax = INT_MIN;
for( int i = center + 1; i <= r; i++ ){
righthalf += nums[i];
righthalfmax = righthalf > righthalfmax ? righthalf : righthalfmax;
}
return MAX(leftmax,rightmax,lefthalfmax+righthalfmax);
}
int MAX(int a,int b,int c){
return max(max(a,b),max(b,c));
}
};
2.DP
dp[i]:dp[0,i]为止最大子序和
状态转移方程
dp[i] = max{dp[i-1]+nums[i],nums[i]}
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> dp(nums.size());
int ans = dp[0] = nums[0];
for( int i = 1; i < nums.size(); i++ ){
dp[i] = max(nums[i],dp[i-1] + nums[i]);
ans = max(dp[i],ans);
}
return ans;
}
};