leetCode 53.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.

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.


思路:這題在剛開始想用雙指針解,可是碼代碼的時候發現雙指針不行,感覺不是非常難的一個題。最后還是要求助網上資料。經過翻找,一個非常好的博文詳解了本題的算法思想。非常清晰,故摘錄在下:

http://blog.csdn.net/joylnwang/article/details/6859677
又一個經典問題。對於一個包括負值的數字串array[1...n],要找到他的一個子串array[i...j](0<=i<=j<=n),使得在array的全部子串中。array[i...j]的和最大。

這里我們須要注意子串和子序列之間的差別。

子串是指數組中連續的若干個元素。而子序列僅僅要求各元素的順序與其在數組中一致,而沒有連續的要求。對於一個元素數為n的數組,其含有2^n個子序列和n(n+1)/2個子串。假設使用窮舉法,則至少須要O(n^2)的時間才干得到答案。卡耐基梅隆大學的Jay Kadane的給出了一個線性時間算法,我們就來看看。怎樣在線性時間內解決最大子串和問題。 要說明Kadane算法的正確性,須要兩個結論。

首先。對於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中和最大子串矛盾。 其次,我們能夠將數組從左到右切割為若干子串,使得除了最后一個子串之外,其余子串的各元素之和小於0,且對於全部子串array[i...j]和隨意k(i<=k<j)。有array[i...k]的和大於0。

此時我們要說明的是。滿足條件的和最大子串,僅僅能是上述某個子串的前綴。而不可能跨越多個子串。我們假設array[p...q]。是array的和最大子串,且array[p...q]。跨越了array[i...j],array[j+1...k]。依據我們的分組方式,存在i<=m<j使得array[i...m]的和是array[i...j]中的最大值,存在j+1<=n<k使得array[j+1...n]的和是array[j+1...k]的最大值。

因為array[m+1...j]使得array[i...j]的和小於0。此時我們能夠比較array[i...m]和array[j+1...n]。假設array[i...m]的和大於array[j+1...n]則array[i...m]>array[p...q]。否array[j+1...n]>array[p...q]。不管誰大,我們都能夠找到比array[p...q]和更大的子串。這與我們的假設矛盾。所以滿足條件的array[p...q]不可能跨越兩個子串。

對於跨越很多其它子串的情況,因為各子串的和均為負值。所以相同能夠證明存在和更大的非跨越子串的存在。

對於單元素和最大的特例,該結論也適用。

依據上述結論,我們就得到了Kadane算法的運行流程,從頭到尾遍歷目標數組,將數組切割為滿足上述條件的子串,同一時候得到各子串的最大前綴和,然后比較各子串的最大前綴和,得到終於答案。我們以array={−2, 1, −3, 4, −1, 2, 1, −5, 4}為例,來簡單說明一下算法步驟。通過遍歷。能夠將數組切割為例如以下3個子串(-2)。(1。-3),(4。-1,2,1,-5,4)。這里對於(-2)這種情況。單獨分為一組。各子串的最大前綴和為-2,1,6,所以目標串的最大子串和為6。


我的代碼,上面博文的代碼有些繁瑣。

public class Solution {
    public int maxSubArray(int[] nums) {
        int max = Integer.MIN_VALUE;//設置最小值
        int sum = 0;//每一個分組的和
        int i = 0;
        while(i < nums.length){
            sum += nums[i];//每一個分組的前n項和
            if(max < sum){
                max = sum;//取最大和
            }
            if(sum < 0){//假設<0。分組結束,開始下一組
                sum = 0;
            }
            i++;
        }
        return max;
    }
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM