1. 程式人生 > >編程之法:面試和算法心得(最大連續子數組和)

編程之法:面試和算法心得(最大連續子數組和)

參考 否則 ++ 例子 返回 log 遍歷 方法 時間

內容全部來自編程之法:面試和算法心得一書,實現是自己寫的使用的是java

題目描述

輸入一個整形數組,數組裏有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。 求所有子數組的和的最大值,要求時間復雜度為O(n)。

例如輸入的數組為1, -2, 3, 10, -4, 7, 2, -5,和最大的子數組為3, 10, -4, 7, 2, 因此輸出為該子數組的和18。

分析與解法

解法一

求一個數組的最大子數組和,我想最直觀最野蠻的辦法便是,三個for循環三層遍歷,求出數組中每一個子數組的和,最終求出這些子數組的最大的一個值。 令currSum[i, …, j]為數組A中第i個元素到第j個元素的和(其中0 <= i <= j < n),maxSum為最終求到的最大連續子數組的和。

且當全是負數的情況時,我們可以讓程序返回0,也可以讓程序返回最大的那個負數,這裏,我們讓程序返回最大的那個負數。

參考代碼如下:

/*
     * 求一個數組的最大子數組和,我想最直觀最野蠻的辦法便是,三個for循環三層遍歷,
     * 求出數組中每一個子數組的和,最終求出這些子數組的最大的一個值。 
     * 令currSum[i, …, j]為數組A中第i個元素到第j個元素的和(其中0 <= i <= j < n),
     * maxSum為最終求到的最大連續子數組的和。
     * 且當全是負數的情況時,我們可以讓程序返回0,也可以讓程序返回最大的那個負數,這裏,我們讓程序返回最大的那個負數。
     
*/ public static int solution1(int[] arr) { int maxSum = arr[0]; for(int i=0;i<arr.length;i++) { for(int j=i;j<arr.length;j++) { int currSum = 0; for(int k=i;k<j;k++) { currSum
+=arr[k]; } maxSum = Math.max(maxSum, currSum); } } return maxSum; }

此方法的時間復雜度為O(n^3)。

解法二

事實上,當我們令currSum為當前最大子數組的和,maxSum為最後要返回的最大子數組的和,當我們往後掃描時,

  • 對第j+1個元素有兩種選擇:要麽放入前面找到的子數組,要麽做為新子數組的第一個元素;
    • 如果currSum加上當前元素a[j]後不小於a[j],則令currSum加上a[j],否則currSum重新賦值,置為下一個元素,即currSum = a[j]。
  • 同時,當currSum > maxSum,則更新maxSum = currSum,否則保持原值,不更新。

currSum = max(a[j], currSum + a[j])
maxSum = max(maxSum, currSum)

舉個例子,當輸入數組是1, -2, 3, 10, -4, 7, 2, -5,那麽,currSum和maxSum相應的變化為:

  • currSum: 0 1 - 1 3 13 9 16 18 13
  • maxSum : 0 1 1 3 13 13 16 18 18

參考代碼如下:

/*
     * 解法二
     * 事實上,當我們令currSum為當前最大子數組的和,maxSum為最後要返回的最大子數組的和,當我們往後掃描時,
     * 對第j+1個元素有兩種選擇:要麽放入前面找到的子數組,要麽做為新子數組的第一個元素;
     * 如果currSum加上當前元素a[j]後不小於a[j],則令currSum加上a[j],否則currSum重新賦值,置為下一個元素,即currSum = a[j]。
     * 同時,當currSum > maxSum,則更新maxSum = currSum,否則保持原值,不更新。
     * 即
     * currSum = max(a[j], currSum + a[j])
     * maxSum = max(maxSum, currSum)
     */
    public static int solution2(int[] arr)
    {
        int maxSum = arr[0];
        int currSum = 0;
        for(int i=1;i<arr.length;i++)
        {
            currSum = Math.max(arr[i], currSum + arr[i]);
            maxSum = Math.max(maxSum, currSum);
        }
        return maxSum;
    }

編程之法:面試和算法心得(最大連續子數組和)