标签:
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.
click to show more practice.
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.
分别给出O(n)时间复杂度和分治解法。
1. O(n)时间复杂度的方法属于动态规划的方法(这是网上的说法,不过楼主不太明白为什么是动态规划)。假设最大和的子串为A[i...j],其中0<i<k<j<n。则A[i,k]的和大于0,否则A[k+1, j]>A[i,j],与假设矛盾。这是该解法的主要思想。代码如下:
public int maxSubArray(int[] A) { int sum = 0; int maxSum = Integer.MIN_VALUE; for(int i=0; i<A.length; i++) { sum = sum + A[i]; if(sum > maxSum) maxSum = sum; if(sum < 0) sum = 0; } return maxSum; }
分治解法的思想是:A[0,n]的最大和子串有三种情况:
1. 在左半子串A[0,n/2];
2. 在右半子串A[n/2 + 1, n];
3. 一部分在左半子串,另一部分在右半子串A[i, j],0<i<n/2<j<n;
对于1,2,继续使用分治法缩小求解范围,由子问题求得原问题;对于3,只需遍历数组,求得以A[n/2]为中间一点的某个子串的和;
取3中情况中的最大值即为原问题的解。代码如下:
public int maxSubArrayDP(int[] A, int start, int over) { if(start > over) return Integer.MIN_VALUE; if(start == over) return A[start]; int mid = (start + over) / 2; int leftMax = maxSubArrayDP(A, start, mid); int rightMax = maxSubArrayDP(A, mid+1, over); int sum = 0; int leftMaxSum = Integer.MIN_VALUE; int rightMaxSum = Integer.MIN_VALUE; for(int i=mid; i>=0; i--) { sum += A[i]; if(sum > leftMaxSum) { leftMaxSum = sum; } } sum = 0; for(int i=mid+1; i<=over; i++) { sum += A[i]; if(sum > rightMaxSum) { rightMaxSum = sum; } } if(leftMax > rightMax) { return (leftMax > (leftMaxSum+rightMaxSum) ? leftMax : (leftMaxSum+rightMaxSum)); } else { return (rightMax > (leftMaxSum+rightMaxSum) ? rightMax : (leftMaxSum+rightMaxSum)); } }
标签:
原文地址:http://www.cnblogs.com/linxiong/p/4288790.html