leetcode -- Maximum Subarray

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.

[解题思路]
如果当前的和小于0,则在后面的数加上现在的和只会比原来的数要小,故舍弃
O(n)就是一维DP.
假设A(0, i)区间存在k,使得[k, i]区间是以i结尾区间的最大值, 定义为Max[i], 在这里,当求取Max[i+1]时,
Max[i+1] = Max[i] + A[i+1],  if (Max[i] + A[i+1] >0)
                = 0, if(Max[i]+A[i+1] <0),如果和小于零,A[i+1]必为负数,没必要保留,舍弃掉
然后从左往右扫描,求取Max数字的最大值即为所求。
 1 public int maxSubArray(int[] A) {
 2         // Start typing your Java solution below
 3         // DO NOT write main() function
 4         int result = Integer.MIN_VALUE;
 5         int curSum = 0;
 6         for(int i = 0; i < A.length; i++){
 7             curSum += A[i];
 8             if(curSum > result){
 9                 result = curSum;
10             }
11             if(curSum < 0){
12                 curSum = 0;
13             }
14         }
15         
16         return result;
17     }

 (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)

你可能感兴趣的:(LeetCode)