LeetCode: Container With Most Water

PS:金融民工搬磚也辛苦,最近項目緩一點,終於又可以擼一擼題,預防下阿爾茨海默症

Container With Most Water

Given n non-negative integers a1, a2, …, an, where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.

Note: You may not slant the container and n is at least 2.

拿到題,首先想到暴力破解法

先上遞歸

public int maxArea(int[] height) {
    if (height == null || height.length < 2) {
        return 0;
    }

    int len = height.length;

    if (len == 2) {
        return min(height[0], height[1]);
    }

    // 計算f(n-1)的結果
    int[] height_1 = new int[len - 1];
    System.arraycopy(height, 0, height_1, 0, len - 1);
    int maxArea = maxArea(height_1);

    for (int i = 0; i < len - 1; i++) {
        int area = (len - 1 - i) * min(height[i], height[len - 1]);
        if (maxArea < area) {
            maxArea = area;
        }
    }
    return maxArea;
}
public int min(int x, int y) {
    return x < y ? x : y;
}

提交後顯示超時,接着不死心又上了個循環

public static int maxArea2(int[] height) {
    if (height == null || height.length < 2) {
        return 0;
    }

    int maxArea = 0;
    int count = height.length - 1;
    for (int i = 0; i < count; i++) {
        for (int j = i + 1; j < height.length; j++) {
            int curArea = (j - i) * min(height[j], height[i]);
            maxArea = maxArea > curArea ? maxArea : curArea;
        }
    }
    return maxArea;
}
public int min(int x, int y) {
    return x < y ? x : y;
}

納尼?還是不行。仔細想想,把所有可能性算一遍,時間複雜度都是O(n2),這題的接受條件可能是O(n)的時間複雜度。

慚愧,想了半個小時,雖然想要拋棄一些比較,但是囿於單指針,沒有想到該怎麼做。so,轉到discuss區,大神提供了一種O(n)的解法,雙指針從兩邊同時掃描(初看讓人有點眩暈,不過邏輯相當清晰)

public int maxArea(int[] height) {
    if (height == null || height.length < 2) {
        return 0;
    }

    int left = 0, right = height.length - 1, maxArea = 0;
    while (left < right) {
        int area = (right - left) * Math.min(height[left], height[right]);
        maxArea = maxArea > area ? maxArea : area;
        if (height[left] < height[right]) {
            left++;
        } else {
            right--;
        }
    }
    return maxArea;
}

這位的解釋非常好,大意是:

  • 現在我們有兩個指針,分別位於兩頭,Xleft=0,Xright=n-1。
  • 現在假設 height[Xleft] < height[Xright],如果畫一個平面座標系,就會發現,當左邊線條不變,右邊取任何線條,都不會比當前情況下所得到的容器的容量大,即是說:不需要計算 Xleft=0,Xright=1,2,…,n-2 這些情況。這個時候就可以放心地將 Xleft 往右移了。
  • 同理,height[Xleft] > height[Xright],向左移動 Xright
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章