53. Maximum Subarray (Array; DP)
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
the contiguous subarray [4,−1,2,1]
has the largest sum = 6
.
More practice:
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
法I:动态规划。max_local存储到i之前的sum,如果<0,表示之前的sum对之后只可能有负贡献,所以忽略,直接考虑nums[i]。max_global存储目前为止出现过的最大sum。
动态转移方程是:
局部最优:max_local= max(max_local+nums[i], nums[i])
全局最优:max_global= max(max_global, max_local)
class Solution { public: int maxSubArray(vector<int>& nums) { int max_local = nums[0]; //maxSum may be negative, so can't simply write int curSum = 0 int max_global = nums[0]; for(int i = 1; i < nums.size(); i++){ max_local = max(max_local+nums[i],nums[i]); max_global = max(max_global, max_local); } return max_global; } };
法II:分治法
将数组分为左右两段,分别找到最大子串和,然后还要从中间开始往两边扫描,求出最大和,比较三个和取最大值。
class Solution { public: int maxSubArray(vector<int>& nums) { return binarySearch(nums,0,nums.size()-1); } int binarySearch(vector<int>& nums, int left, int right){ //right=left<=1的两种情况都要讨论 if(left==right) return nums[left]; if(right-left == 1){ return max(max(nums[left],nums[right]),nums[left]+nums[right]); } int mid = left +((right-left)>>1); int leftmax = binarySearch(nums, left, mid); int rightmax = binarySearch(nums, mid+1, right); int curLeft = nums[mid],curRight=nums[mid+1], maxLeft=nums[mid], maxRight=nums[mid+1]; for(int i = mid-1; i>=left; i--){ curLeft+=nums[i]; maxLeft = max(curLeft,maxLeft); } for(int i = mid+2; i <= right; i++){ curRight+=nums[i]; maxRight = max(curRight,maxRight); } return max(max(leftmax,rightmax),maxLeft+maxRight); } };