1. 程式人生 > >Java&LeetCode 初入門——053. 最大子序和

Java&LeetCode 初入門——053. 最大子序和

Java&LeetCode 初入門——053. 最大子序和


文內程式碼全部採用JAVA語言。

題目

給定一個整數陣列 nums ,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
進階:如果你已經實現複雜度為 O(n) 的解法,嘗試使用更為精妙的分治法求解。
示例:

輸入: [-2,1,-3,4,-1,2,1,-5,4],
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6

個人解法

本人表示本人太渣了,這題完全沒想到如何降低複雜度,除了遍歷還是遍歷。個人程式碼以及長到超出時間限制,哭暈在廁所。以後還是要多學習才行。就不把我的程式碼貼出來丟人現眼了。直接學習大神們的解法吧。

大神解法

思路

其實有一個想法很好理解,就是當前面幾個數的和小於0時,就沒必要帶上這幾個數了,因為越帶越小。比如[-1,-2,5,7,-3,-4,5],從前往後依次看,第一個讀取的數是-1,雖然是負數,但沒有讀取下一個數之前,它是目前的最大值,放在res中。但是負數對於求和取最大值起到的是反作用,所以如果取下一個值的時候,還不如丟掉-1,直接取-2,也比(-1)+(-2)來的划算。第二個和值直接為-2,放在sum中,和res比較,取較大值放在res中。目前的sum依舊小於0,對和值沒有幫助,第三個和值直接為5,放在sum中,和res比較,取較大值放在res中。以此類推。

其實簡單來講就是一個指標,從頭指到尾。繼續看[-1,-2,5,7,-3,-4,5],看指標前面的sum是不是大於0,大於0的sum的子序列對整個連續子陣列的最大值有幫助。比如指標指到7時,7前面連續的最大的sum是5,那麼整個連續子陣列可以納入5。小於0的sum對整個連續子陣列的最大值起反作用,直接拋棄前面的sum。比如指標指到5時,前面的sum=-2,沒有幫助,還不如不要,所以指標5時,連續子陣列中只有[5]。

自己找個陣列除錯一遍,很快就能明白了。

演算法

16 ms, 在Maximum Subarray的Java提交中擊敗了60.83% 的使用者。
我覺得挺厲害的了,能想到這樣的解法真是666(忽略我的垃圾水平)。

class Solution {
    public int maxSubArray(int[] nums) {
        int res = nums[0];
        int sum = 0;
        for (int num : nums) {
            if (sum > 0)
                sum += num;
else sum = num; res = Math.max(res, sum); } return res; } }

範例區最快的解法

class Solution {
    public int maxSubArray(int[] nums) {
        int sum = 0, max = Integer.MIN_VALUE;
        for(int i = 0; i < nums.length; i++){
            sum = sum<0? nums[i] : (sum+nums[i]);
            max = Math.max(sum, max);
        }
        return max;
    }
}

區別不大,只是在於max的初始值和一個三元運算子,思路基本一致。