[LeetCode49]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.

Analysis:

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数字的最大值即为所求。

Java

public int maxSubArray(int[] A) {
        int max = 0;
		int res = Integer.MIN_VALUE;
		for(int i=0;i<A.length;i++){
			max = max>=0 ? (max+A[i]):A[i];
			res = Math.max(max, res);
		}
		return res;
    }
c++
int maxSubArray(int A[], int n) {
        int sum = 0;
    int res = INT_MIN;
    for(int i=0;i<n;i++){
        sum = sum>=0?(sum+A[i]):A[i];
        res = max(sum,res);
    }
    return res;
    }
Solution2:

采用Divide & 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)的解。

Java

public int maxSubArray(int[] A) {
        int res  = Integer.MIN_VALUE;
		return getMaxSubarray(A, 0, A.length-1, res);
    }
    public int getMaxSubarray(int A[],int left, int right, int smax){
	    if(left>right)
	        return Integer.MIN_VALUE;
	    int mid = (left+right)/2;
	    int lmax = getMaxSubarray(A,left,mid-1,smax);
	    int rmax = getMaxSubarray(A,mid+1,right,smax);
	    smax = Math.max(lmax,smax);
	    smax = Math.max(rmax,smax);
	    int sum =0, mlmax = 0;
	    for(int i=mid-1;i>=left;i--){
	        sum+=A[i];
	        if(sum>mlmax)
	            mlmax = sum;
	    }
	    sum = 0;
	    int mrmax = 0;
	    for(int i=mid+1;i<=right;i++){
	        sum+=A[i];
	        if(sum>mrmax)
	            mrmax = sum;
	    }
	    smax = Math.max(smax, mlmax+mrmax+A[mid]);
	    return smax;
	}

c++

int getMaxSubarray(int A[],int left, int right, int smax){
    if(left>right)
        return INT_MIN;
    int mid = (left+right)/2;
    int lmax = getMaxSubarray(A,left,mid-1,smax);
    int rmax = getMaxSubarray(A,mid+1,right,smax);
    smax = max(lmax,smax);
    smax = max(rmax,smax);
    int sum =0, mlmax = 0;
    for(int i=mid-1;i>=left;i--){
        sum+=A[i];
        if(sum>mlmax)
            mlmax = sum;
    }
    sum = 0;
    int mrmax = 0;
    for(int i=mid+1;i<=right;i++){
        sum+=A[i];
        if(sum>mrmax)
            mrmax = sum;
    }
    smax = max(smax, mlmax+mrmax+A[mid]);
    return smax;
}
    int maxSubArray(int A[], int n) {
        int maxv = INT_MIN;
        return getMaxSubarray(A,0,n-1,maxv);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值