1. 程式人生 > >LeetCode---53. Maximum Subarray

LeetCode---53. Maximum Subarray

53. Maximum Subarray

題目

思路及解法

這裡我們須要注意子串和子序列之間的差別。 子串是指陣列中連續的若干個元素。而子序列僅僅要求各元素的順序與其在陣列中一致,而沒有連續的要求。對於一個元素數為n的陣列,其含有2n2^{n} 個子序列和n(n+1)2\frac{n(n+1)}{2}個子串。

另外,我們還需要知道一個結論。對於array[1…n],假設array[i…j]就是滿足和最大的子串,那麼對於不論什麼k(i<=k<=j),我們有array[i…k]的和大於0。因為假設存在k使得array[i…k]的和小於0。那麼我們就有array[k+1…j]的和大於array[i…j],這與我們假設的array[i…j]就是array中和最大子串矛盾。 簡單說,就是在這個子串的範圍內,某個元素前面的子子串一定大於零

方法一

首先我們遍歷每一個元素,做兩個判斷,第一,當前元素是不是要和其他元素組成一個子串,也就是這個元素是不是要放到當前的子串裡。第二,如果當前子串不是最大子串了,我們怎麼更新一個子串。 假設我們現在站在某一個元素k的位置上,他的前面已經有一個子串了,這時候如果這個子串的和是小於零的,根據我們上面給出的結論,這個子串一定不是最大子串,所以我們應該更新子串。那麼有一個問題是新的子串的起始位置在哪裡呢?其實,我們知道這個子串是我們一步一步迭代來的,也就是這個子串的每一個子串都是經過這個方法得來的,所以他們都滿足上面說的結論。如果這個起始位置在這個子串的內部,比如位置x,那麼x前面的子子串是大於零的,而本身這個子串小於零,所以x後面的子子串也一定小於零,那麼將x作為起始位置相當於給新的子串增加了一個小於零的子子串,根據結論,這個新的子串一定不是最大和子串。所以,新的起始位置一定不在子串的內部,應該在位置k。 如果這個子串是大於零的,根據結論,我們是可以吧k放到這個子串裡的,但是我們並不能保證加入k後子串的和變大,因為k可能小於零,但同時s後面的元素加入子串後有可能使得子串和變大。所以我們就把符合結論的子串的和通過一個result變數記錄下來,在每一次更新子串後,看看新的子串和是不是比result大了,如果是,就更新result,否則result保持不變。最終,我們輸出result就行了。 但是這種方法的效率低,只有11%

方法一
class Solution {
    public int maxSubArray(int[] nums) {
        int result = nums[0];
        int k = nums[0];
        
        for(int i=1; i<nums.length; i++){
            if(k<0){
                k = nums[i];
            }else{
                k += nums[i];
            }
            if(k>result){
                result = k;
            }
        }
        return result;
    }
}