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
.
If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
思路一:
遍历数组元素,每次加一个新的元素,如果当前和sum>之前保存的结果result,令result=sum;如果sum<0,令sum=0.最后result保存的就是最大的和值。
思路二:
就是实现题目中说到的divide and conquer approach。
1)将数组从mid分成left、right两部分,迭代找到leftMax和rightMax。令subMax=max(leftMax,rightMax)
2)然后是找mid连接的左右两边的元素的最大值。
先找mid左边的和最大值leftContigousMax(一定要包含nums[mid],不然不是连续的和了),如果leftContigousMax就可以直接返回subMax了(因为这时可以肯定右边的最大值rightMax是最大的)。
同理,找到mid右边的和最大值rightContigousMax,如果rightContigousMax<0,直接返回subMax;
否则返回max(subMax,leftContigousMax+rightContigousMax)。
代码实现一:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
if(nums.size() < 1) return 0;
int result = INT_MIN;
int sum = 0;
for(auto num: nums)
{
sum += num;
if(sum > result) result = sum;
if(sum < 0) sum = 0;
}
return result;
}
};
代码2实现:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
return maxSubArrayRec(nums, 0, nums.size() -1);
}
private:
int maxSubArrayRec(vector<int>&nums, int i, int j) {
if(i==j)
return nums[i];
int mid = (i + j) / 2;
int leftMax = maxSubArrayRec(nums,i,mid);
int rightMax = maxSubArrayRec(nums,mid+1,j);
int subMax = max(leftMax,rightMax);
int leftContiguousMax = nums[mid];
int leftSum = nums[mid];
for(int k=mid-1; k>=i; k--) {
leftSum += nums[k];
if(leftSum > leftContiguousMax)
leftContiguousMax = leftSum;
}
if(leftContiguousMax <= 0)
return subMax;
int rightContigousMax = nums[mid+1];
int rightSum = nums[mid+1];
for(int k=mid+2; k<=j; k++) {
rightSum += nums[k];
if(rightSum > rightContigousMax)
rightContigousMax = rightSum;
}
if(rightContigousMax <= 0)
return subMax;
return max(subMax,leftContiguousMax+rightContigousMax);
}
};