Labels

Monday, February 2, 2015

Maximum Subarray


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.

Naive Way: 一个感觉觉得跟sell stock那题很像,可以用DP吧,先试一试。

基本逻辑为:
opt[i,j] // 表示从i到j的maximum subarray。
才写第一句就发现这样一来就是O(n^2)的复杂度了。但是感觉这一题应该是能在O(n)的时间内算出来的。

一个比较直观的想法就是用指针控制记录有效区段首尾。一旦遇到整数,就有可能要替换最大值,一旦遇到负数,只要当前和仍大于零,就可以将该负数加入有效区段内。这里自己还漏掉了全是负数的情况 ,但这种情况其实很简单,全是负数时最大的和就是其中一个负数,每次取到负数都与最大值进行比较则可将该情况囊括。


public class Solution {
    public int maxSubArray(int[] A) {
        int begin = 0, end = 0;
        if(A.length == 0){return 0;}
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for(int i = 0;i < A.length;i++){
            if(A[i] >= 0){
                if(sum <= 0){
                    while(begin!=end){begin++;}
                    sum = 0;
                }
                max = Math.max(sum + A[i], max);
            }else{
                max = Math.max(max,A[i]);
            }
            end++;
            sum += A[i];
        }
        return max;
    }
}


最后看来一个人的discuss发现跟我的一模一样,就是没有begin 和 end。这才发现begin和end在这段代码中没有作用,删除掉。

public class Solution {
    public int maxSubArray(int[] A) {
        if(A.length == 0){return 0;}
        int max = Integer.MIN_VALUE;
        int sum = 0;
        for(int i = 0;i < A.length;i++){
            if(A[i] >= 0){
                if(sum <= 0)
                    sum = 0;
                max = Math.max(sum + A[i], max);
            }else{
                max = Math.max(max,A[i]);
            }
            sum += A[i];
        }
        return max;
    }
}

最终版本应该是这样的:(来自leetcode用户 AlexTheGreat)

public int maxSubArray(int[] A) {
    int max = Integer.MIN_VALUE, sum = 0;
    for (int i = 0; i < A.length; i++) {
        if (sum < 0) 
            sum = A[i];
        else 
            sum += A[i];
        if (sum > max)
            max = sum;
    }
    return max;
}
 
 
Improved Way: 看见leetcode上有人提问这道题用divide and conquer做,
一位大神回答了说divide and conquer是 O(nlogn)。那么就懂如果要
divide and conquer是怎么回事,每次都得对比两边的最大subarray sum和
中间部分有可能的subarray sum,想想都觉得很麻烦,还是先不写了。





 

No comments:

Post a Comment