package Level3;
import java.util.Arrays;
/**
*
* 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.
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.
*
*/
public class S53 {
public static void main(String[] args) {
int[] A = {1,2,-1,-2,2,1,-2,1,4,-5,4};
System.out.println(maxSubArray(A));
}
// 一维DP,可省略掉dp数组
public static int maxSubArray(int[] A) {
int max = A[0];
int[] sum = new int[A.length];
sum[0] = A[0];
for(int i=1; i<A.length; i++){
// 要么不用前面的结果,要么用,求两者较大的
sum[i] = Math.max(A[i], sum[i-1]+A[i]);
max = Math.max(max, sum[i]);
}
// System.out.println(Arrays.toString(sum));
return max;
}
}
memory优化版,不用数组存了!
public class Solution {
public int maxSubArray(int[] A) {
int max = A[0];
int maxEndHere = A[0];
for(int i=1; i<A.length; i++){
maxEndHere = Math.max(A[i], maxEndHere+A[i]);
max = Math.max(max, maxEndHere);
}
return max;
}
}
Divide & Conquer
// http://www.geeksforgeeks.org/largest-sum-contiguous-subarray/
public class MaximumSubarray {
public static void main(String[] args) {
// int[] a = {-2,-3,4,-1,-2,1,5,-3};
// int[] a = {-2,-3,-4,-1,-2,-1,-5,-3};
int[] a = {-2, -5, 6, -2, -3, 1, 5, -6};
System.out.println(maxSubArraySum2(a));
System.out.println(maxSubArraySumDC(a, 0, a.length-1));
}
public static int maxSubArraySum(int[] a){
int maxSoFar = 0, maxEndingHere = 0;
int _maxStartIndexSoFar_ = -1;
int _maxStartIndexEndingHere_ = -1;
int _maxEndIndexSoFar_ = -1;
for(int i=0; i<a.length; i++){
if(maxEndingHere < 0){
maxEndingHere = 0;
}else{
if(maxEndingHere == 0){
_maxStartIndexEndingHere_ = i;
}
maxEndingHere += a[i];
}
if(maxEndingHere > maxSoFar){
maxSoFar = maxEndingHere;
_maxEndIndexSoFar_ = i;
_maxStartIndexSoFar_ = _maxStartIndexEndingHere_;
}
}
System.out.println("range: " + _maxStartIndexSoFar_ + " , " + _maxEndIndexSoFar_);
return maxSoFar;
}
// Handling negative
public static int maxSubArraySum2(int[] a){
int maxSoFar = a[0], maxEndingHere = a[0];
for(int i=1; i<a.length; i++){
maxEndingHere= Math.max(a[i], maxEndingHere+a[i]);
maxSoFar = Math.max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}
// Divide and Conquerer O(nlogn)
// http://www.geeksforgeeks.org/divide-and-conquer-maximum-sum-subarray/
public static int maxSubArraySumDC(int[] a, int l, int h){
if(l == h){
return a[l];
}
// Find the mid point
int m = (l+h)/2;
return Math.max(Math.max(maxSubArraySumDC(a, l, m),
maxSubArraySumDC(a, m+1, h)),
maxCrossingSum(a, l, m, h));
}
private static int maxCrossingSum(int[] a, int l, int m, int h) {
int sum = 0;
int leftSum = Integer.MIN_VALUE;
for(int i=m; i>=l; i--){
sum += a[i];
if(sum > leftSum){
leftSum = sum;
}
}
sum = 0;
int rightSum = Integer.MIN_VALUE;
for(int i=m+1; i<=h; i++){
sum += a[i];
if(sum > rightSum){
rightSum = sum;
}
}
return leftSum + rightSum;
}
// Leetcode when to buy stock
}
每个元素都可以选择用前面的curSum(如果是正数)或是不用(curSum为负)
public class Solution {
public int maxSubArray(int[] A) {
int len = A.length;
if(len == 0){
return 0;
}
int curSum = A[0];
int maxSum = A[0];
for(int i=1; i<len; i++){
if(curSum < 0){
curSum = A[i];
}else{
curSum += A[i];
}
maxSum = Math.max(maxSum, curSum);
}
return maxSum;
}
}