【LeetCode】53. Maximum Subarray

問題描述

問題鏈接:https://leetcode.com/problems/maximum-subarray/#/description

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.

我的代碼

這可是我第一次獨立做出來動規的題,雖然是最簡單的,不過還是好開心啊,哈哈。

public class Solution {
    public int maxSubArray(int[] nums) {
        /*
        專項練習,所以思路肯定是用動規,那麼重點就是表示狀態和找出狀態轉移方程。
        狀態轉移方程的核心思想就是之前的積累如果是正的,那麼就是有用的,應該加上,否則負的沒啥用,就棄了算了
        狀態表示:s[i]表示以第i個位置結尾的子串的最大和,那麼最後問題的解就是max(s[i])
        狀態轉移方程:s[i] = s[i - 1] > 0?s[i - 1] + nums[i]:nums[i]
        */

        int len = nums.length;
        int maxSum = Integer.MIN_VALUE;
        int[] s = new int[len];

        s[0] = nums[0];
        maxSum = s[0];
        for(int i = 1; i < len; i++){
            s[i] = s[i - 1] > 0 ? s[i - 1] + nums[i] : nums[i];
            if(s[i] > maxSum){
                maxSum = s[i];
            }
        }
        return maxSum;
    }
}

打敗了62.86%的Java代碼。來到討論區學習一下。

討論區

DP solution & some thoughts

鏈接地址:https://discuss.leetcode.com/topic/6413/dp-solution-some-thoughts

思考的過程是非常棒的。

Analysis of this problem:
Apparently, this is a optimization problem, which can be usually solved by DP. So when it comes to DP, the first thing for us to figure out is the format of the sub problem(or the state of each sub problem). The format of the sub problem can be helpful when we are trying to come up with the recursive relation.

At first, I think the sub problem should look like: maxSubArray(int A[], int i, int j), which means the maxSubArray for A[i: j]. In this way, our goal is to figure out what maxSubArray(A, 0, A.length - 1) is. However, if we define the format of the sub problem in this way, it’s hard to find the connection from the sub problem to the original problem(at least for me). In other words, I can’t find a way to divided the original problem into the sub problems and use the solutions of the sub problems to somehow create the solution of the original one.

So I change the format of the sub problem into something like: maxSubArray(int A[], int i), which means the maxSubArray for A[0:i ] which must has A[i] as the end element. Note that now the sub problem’s format is less flexible and less powerful than the previous one because there’s a limitation that A[i] should be contained in that sequence and we have to keep track of each solution of the sub problem to update the global optimal value. However, now the connect between the sub problem & the original one becomes clearer:

maxSubArray(A, i) = maxSubArray(A, i - 1) > 0 ? maxSubArray(A, i - 1) : 0 + A[i]; 

And here’s the code

public int maxSubArray(int[] A) {
        int n = A.length;
        int[] dp = new int[n];//dp[i] means the maximum subarray ending with A[i];
        dp[0] = A[0];
        int max = dp[0];

        for(int i = 1; i < n; i++){
            dp[i] = A[i] + (dp[i - 1] > 0 ? dp[i - 1] : 0);
            max = Math.max(max, dp[i]);
        }

        return max;
}

Accepted O(n) solution in java

鏈接地址:https://discuss.leetcode.com/topic/5000/accepted-o-n-solution-in-java

這個講得好清楚,經典方法一定要背下來。

this problem was discussed by Jon Bentley (Sep. 1984 Vol. 27 No. 9 Communications of the ACM P885)

the paragraph below was copied from his paper (with a little modifications)

algorithm that operates on arrays: it starts at the left end (element A[1]) and scans through to the right end (element A[n]), keeping track of the maximum sum subvector seen so far. The maximum is initially A[0]. Suppose we’ve solved the problem for A[1 .. i - 1]; how can we extend that to A[1 .. i]? The maximum
sum in the first I elements is either the maximum sum in the first i - 1 elements (which we’ll call MaxSoFar), or it is that of a subvector that ends in position i (which we’ll call MaxEndingHere).

MaxEndingHere is either A[i] plus the previous MaxEndingHere, or just A[i], whichever is larger.

public static int maxSubArray(int[] A) {
    int maxSoFar=A[0], maxEndingHere=A[0];
    for (int i=1;i<A.length;++i){
        maxEndingHere= Math.max(maxEndingHere+A[i],A[i]);
        maxSoFar=Math.max(maxSoFar, maxEndingHere); 
    }
    return maxSoFar;
}
發佈了187 篇原創文章 · 獲贊 102 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章