1. 程式人生 > >面試現場:連續子陣列的最大和

面試現場:連續子陣列的最大和

題目

輸入一個整型陣列,數組裡有正數也有負數。陣列中一個或連續的多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間複雜度為O(n)。

舉例

輸入:2, -3, 4, 5, -9

輸出:9

和最大的連續子陣列是 {4, 5},結果就是9。

思路

我們先假設和最大連續子陣列是從第一個數開始的。初始化和為0。第一步是加上數字2,此時和為2。第二步加上數字-3,此時和為-1。那麼問題來了,我們到底要不要加上數字-3呢?分析過程如下:

  1. 加上-3。此時的和為-1,然後由-1繼續加下一個數。
  2. 不加-3。也就是意味當前連續子陣列就終結於-3之前的數字,下一個連續子陣列的和初始化為0,再加上第一個數字-3,和為-3。

由上述分析可知,加上-3,此時累加的子陣列和是-1;不加-3,此時累加的子陣列和是-3。-1大於-3,為了後續的累加和更大,所以選擇加上-3。

接下來,第三步要不要加上數字4,我們依據上面的決策流程繼續分析。當加上數字4,此時累加和為4-1=3;不加上數字4,意味著當前連續子陣列終結於數字4之前,此時的累加和初始化為0,加上數字4後和等於4。顯而易見,4大於3,所以我們選擇拋棄前面的累加和,由數字4繼續開始。

後續步驟省略,總結一番。當我們遍歷陣列時,對於每個數字,要麼與前面的子陣列累加,要麼作為新子陣列的起點,如果累加之後的子陣列和小於(或等於)當前數字,我們就選擇拋棄前面的累加和,將當前數字作為新子陣列的起點。整個過程可以用表格總結如下:

步驟 操作 累加的子陣列和 最大的子陣列和
1 加2 2 2
2 加-3 -1 2
3 拋棄累加的和-1,加4 4 4
4 加5 9 9
5 加-9 0 9

程式碼

根據題目要求,我們只需要求出連續子陣列的最大和,如果面試官還要求找到連續子陣列的起點與終點下標,那麼最終的java程式碼如下:

public class Main {

    public static int child_sum(int[] arr) {
        if (arr == null || arr.length < 1) {
            return 0;
        }

        int left0 = 0;
        int left1 = 0;
        int right = 0;
        int max = arr[0];
        int sum = 0;

        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
            if (sum <= arr[i]) { //使用<=還是<呢?
                sum = arr[i];
                left0 = i;
            }
            if (sum > max) {
                max = sum;
                left1 = left0;
                right = i;
            }
        }

        System.out.println("left:" + left1 + " right:" + right + " max:" + max);
        return max;
    }

    public static void main(String[] args) {
        int[] arr1 = new int[]{2, -3, 4, 5, -9};
        int[] arr2 = new int[]{2, -2, 4, 5, -9};
        int[] arr3 = new int[]{-2, -3, -4, -5, -9};
        child_sum(arr1);
        child_sum(arr2);
        child_sum(arr3);
    }
}

列印輸出:

left:2 right:3 max:9
left:2 right:3 max:9
left:0 right:0 max:-2

在上面的程式碼中使用小於等於或者使用小於有什麼區別呢?

假設陣列為{2, -2, 4, 5, -9},如果判斷條件是小於等於當前數字,那麼所得的最大連續子陣列為{4, 5}。如果判斷條件是小於當前數字,那麼所得的最大連續子陣列為{-2, 2, 4, 5}。如果對最大連續子陣列的長度沒有明確要求,使用小於等於進行判斷即可