1. 程式人生 > >leetCode 11 Container With Most Water

leetCode 11 Container With Most Water

題目描述(中等難度)

每個陣列代表一個高度,選兩個任意的柱子往裡邊倒水,能最多倒多少水。

解法一 暴力解法

直接遍歷任意兩根柱子,求出能存水的大小,用一個變數儲存最大的。

public int maxArea(int[] height) {
    int max = 0;
    for (int i = 0; i < height.length; i++) {
        for (int j = i + 1; j < height.length; j++) {
            int h = Math.min(height[i], height[j]);
            if
(h * (j - i) > max) { max = h * (j - i); } } } return max; }

時間複雜度:O(n²)。

空間複雜度:O(1)。

解法二

我們理一下思路,大小是由長度和高度決定,如果選 0 到 8 就保證了長度最長,此時大小是 0 號柱子的高度 1 乘以長度 8 。我們如果想面積更大怎麼做呢,只能減小長度,增加高度。是左邊的柱子向右移動變成 1 號柱子呢?還是右邊的柱子向左移動變成 7 號柱子呢?當然是哪邊的柱子短就改哪邊的!只有這樣,高度才有可能增加。

例如我們如果把 8 號柱子變成 7 號柱子,此時長度減少了,然而高度還是 0 號柱子沒有變化,所以面積就會減少。把 1 號柱子變成 2 號柱子就很好了,因為此時高度就變成了 8 號柱子的高度,面積就有可能會增加。

如果左右兩邊柱子相等該怎麼辦呢?隨意!

我們假設 1 號 和 8 號 柱子高度是相等的。如果他們之間的柱子只有 1 根比它倆高或者沒有比它倆高的,那麼最大面積就一定選取是 1 號和 8 號了,所以 1 號接著變大,或者 8 號接著減小都是無所謂的,因為答案已經確定了。

假設 1 號 和 8 號之間有 2 根或以上的柱子比它倆高,假設是 4 號和 6 號比它倆高。1 號會變到 2 號、3 號,最終為 4 號,8 號會變到 7 號, 6 號,而在這個過程中產生的面積一定不會比 1 號和 8 號產生的面積大,因為過程中的柱子都比 1 號和 8 號低。所以是先變 1 號還是先變 8 號是無所謂的,無非是誰先到達更長的柱子而已。

看一下下邊的演算法,會更加清楚一些。

public int maxArea2(int[] height) {
    int maxarea = 0, l = 0, r = height.length - 1;
    while (l < r) {
        maxarea = Math.max(maxarea, Math.min(height[l], height[r]) * (r - l));
        if (height[l] < height[r])
            l++;
        else
            r--;
    }
    return maxarea;
}

時間複雜度:O(n)。

空間複雜度:O(1)。

為了減少暴力解法的時間複雜度,只能去深層次的理解題意,從而找出突破點。