Maximum Subarray 最大子数组和(连续)@LeetCode

148 篇文章 69 订阅
27 篇文章 0 订阅
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;
    }
}



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值