class Solution {
public:
int maxSubArray(int A[], int n) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if(n==0)
return 0;
int nStart=A[n-1];
int nAll=A[n-1];
for(int i=n-2;i>=0;i--)//O(n)
{
nStart=(nStart+A[i])>A[i]?(nStart+A[i]):A[i];
nAll=nAll>nStart?nAll:nStart;
}
return nAll;
}
};
(2) Divide and Conquer
二分法:将数组分成左右两部分,递归求两部分最大连续子数组,由于最大连续子数组可能横跨左右,故需对这种情况进行处理
假设数组A[left, right]存在最大值区间[i, j](i>=left & j<=right),以mid = (left + right)/2 分界,无非以下三种情况:
subarray A[i,..j] is
(1) Entirely in A[low,mid-1]
(2) Entirely in A[mid+1,high]
(3) Across mid
对于(1) and (2),直接递归求解即可,对于(3),则需要以min为中心,向左及向右扫描求最大值,意味着在A[left, Mid]区间中找出A[i..mid], 而在A[mid+1, right]中找出A[mid+1..j],两者加和即为(3)的解。
比较三种情况下得到的子数组和,取其中最大值
1 public int maxSubArray(int[] A) { 2 // Start typing your Java solution below 3 // DO NOT write main() function 4 int max = Integer.MIN_VALUE; 5 return maxArray(A, 0, A.length - 1, max); 6 } 7 8 int maxArray(int[] A, int left, int right, int max){ 9 if(left > right){ 10 return Integer.MIN_VALUE; 11 } 12 13 int mid = (left + right) / 2; 14 int leftMax = maxArray(A, left, mid - 1, max); 15 int rightMax = maxArray(A, mid + 1, right, max); 16 17 max = Math.max(max, leftMax); 18 max = Math.max(max, rightMax); 19 20 int sum = 0, mlmax = 0; 21 for(int i = mid - 1; i >= left; i--){ 22 sum += A[i]; 23 if(sum > mlmax){ 24 mlmax = sum; 25 } 26 } 27 sum = 0; int mrmax = 0; 28 for(int i = mid + 1; i <= right; i++){ 29 sum += A[i]; 30 if(sum > mrmax){ 31 mrmax = sum; 32 } 33 } 34 max = Math.max(max, A[mid] + mlmax + mrmax); 35 return max; 36 }
时间复杂度: T(N) = 2*T(N/2) + O(N) 由主定理得 O(NlogN)