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.
这是一道典型动态规划问题。其核心在于找到子问题(So when it comes to DP, the first thing for us to figure out is the format of the sub problem(or the state of each sub problem). The format of the sub problem can be helpful when we are trying to come up with the recursive relation.)
我们从第一个元素开始向后退,在第i个元素时,想要求的是必须包含这个元素且这个元素作为最后一个元素的子数组的最大值maxSubArray(int A[], int i),并且已经解得必须包含其之前一个元素的子数组的最大值maxSubArray(int A[], int i-1),那么maxSubArray(A, i) = maxSubArray(A, i - 1) > 0 ? maxSubArray(A, i - 1) : 0 + A[i]; 再用maxSubArray(A, i)和之前的max进行比较,较大者就是新的max。
public int maxSubArray(int[] A) {
int n = A.length;
int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
dp[0] = A[0];
int max = dp[0];
for(int i = 1; i < n; i++){
dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
max = Math.max(max, dp[i]);
}
return max;
}
Step1. Select the middle element of the array.
So the maximum subarray may contain that middle element or not.
Step 2.1 If the maximum subarray does not contain the middle element, then we can apply the same algorithm to the the subarray to the left of the middle element and the subarray to the right of the middle element.
Step 2.2 If the maximum subarray does contain the middle element, then the result will be simply the maximum suffix subarray of the left subarray plus the maximum prefix subarray of the right subarray
Step 3 return the maximum of those three answer.
class Solution {
public:
int maxSubArray(int A[], int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if(n==0) return 0;
return maxSubArrayHelperFunction(A,0,n-1);
}
int maxSubArrayHelperFunction(int A[], int left, int right) {
if(right == left) return A[left];
int middle = (left+right)/2;
int leftans = maxSubArrayHelperFunction(A, left, middle);
int rightans = maxSubArrayHelperFunction(A, middle+1, right);
int leftmax = A[middle];
int rightmax = A[middle+1];
int temp = 0;
for(int i=middle;i>=left;i--) {
temp += A[i];
if(temp > leftmax) leftmax = temp;
}
temp = 0;
for(int i=middle+1;i<=right;i++) {
temp += A[i];
if(temp > rightmax) rightmax = temp;
}
return max(max(leftans, rightans),leftmax+rightmax);
}
};
本文介绍了一种寻找数组中最大子数组和的算法,通过动态规划和分而治之两种方法实现。动态规划方法利用子问题求解当前问题,分而治之方法则通过递归分解问题,并结合中间结果得出最终答案。
742

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



