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.
http://oj.leetcode.com/problems/maximum-subarray/
Solution:
Still simple dp. Add the element from the start. If sum > max, update sum, if sum < 0, reset sum to 0.
And for the divide and conquer solution, obviously we need to use binary partition. The result would only be 3 conditions:
1, in left half; 2, in right half; 3, cross the middle
For 1st and 2nd condition, we can use recursion. For 3rd condition, we can scan the array from middle and find the maximum sub array in left half and right half.
https://github.com/starcroce/leetcode/blob/master/maximum_subarray.cpp
class Solution {
public:
int maxSubArray(int A[], int n) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int max = -10000;
int current = 0;
for(int i = 0; i < n; i++){
current += A[i];
if(current > max){
max = current;
}
if(current < 0){
current = 0;
}
}
return max;
}
};
// 68 ms for 200 test cases
// divide and conquer solution, O(nlogn)
class Solution {
public:
int maxSubArray(int A[], int n) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
int totalMax = INT_MIN;
return maxSubArray(A, 0, n-1, totalMax);
}
int maxSubArray(int A[], int start, int end, int &totalMax) {
if(start > end) {
return INT_MIN;
}
int middle = (start + end) / 2;
// recursive to left half and right half
int leftMax = maxSubArray(A, start, middle-1, totalMax);
int rightMax = maxSubArray(A, middle+1, end, totalMax);
// update the max
totalMax = max(max(totalMax, rightMax), leftMax);
// start from middle, find the maximum subarray in left and right
int sum = 0, curLeftMax = 0, curRightMax = 0;
for(int i = middle-1; i >= start; i--) {
sum += A[i];
if(sum > curLeftMax) {
curLeftMax = sum;
}
}
sum = 0;
for(int i = middle+1; i <= end; i++) {
sum += A[i];
if(sum > curRightMax) {
curRightMax = sum;
}
}
// update the max
totalMax = max(totalMax, curLeftMax + A[middle] + curRightMax);
return totalMax;
}
};
本文介绍了一种寻找具有最大和的连续子数组的算法。通过动态规划方法,可以在O(n)的时间复杂度内解决问题,并提供了分治策略实现,进一步探讨了不同情况下的解决方案。
212

被折叠的 条评论
为什么被折叠?



