mid 盛最多水的容器

題目

給你 n 個非負整數 a1,a2,…,an,每個數代表座標中的一個點 (i, ai) 。在座標內畫 n 條垂直線,垂直線 i 的兩個端點分別爲 (i, ai) 和 (i, 0)。找出其中的兩條線,使得它們與 x 軸共同構成的容器可以容納最多的水。

說明:你不能傾斜容器,且 n 的值至少爲 2。
在這裏插入圖片描述
示例:

輸入:[1,8,6,2,5,4,8,3,7]
輸出:49

方法

我們先從題目中的示例開始,一步一步地解釋雙指針算法的過程。稍後再給出算法正確性的證明。

題目中的示例爲:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
在初始時,左右指針分別指向數組的左右兩端,它們可以容納的水量爲 \min(1, 7) * 8 = 8min(1,7)∗8=8。

此時我們需要移動一個指針。移動哪一個呢?直覺告訴我們,應該移動對應數字較小的那個指針(即此時的左指針)。這是因爲,由於容納的水量是由

兩個指針指向的數字中較小值 * 指針之間的距離
兩個指針指向的數字中較小值∗指針之間的距離

決定的。如果我們移動數字較大的那個指針,那麼前者「兩個指針指向的數字中較小值」不會增加,後者「指針之間的距離」會減小,那麼這個乘積會減小。因此,我們移動數字較大的那個指針是不合理的。因此,我們移動 數字較小的那個指針。

有讀者可能會產生疑問:我們可不可以同時移動兩個指針? 先別急,我們先假設 總是移動數字較小的那個指針 的思路是正確的,在走完流程之後,我們再去進行證明。

所以,我們將左指針向右移動:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此時可以容納的水量爲 \min(8, 7) * 7 = 49min(8,7)∗7=49。由於右指針對應的數字較小,我們移動右指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此時可以容納的水量爲 \min(8, 3) * 6 = 18min(8,3)∗6=18。由於右指針對應的數字較小,我們移動右指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此時可以容納的水量爲 \min(8, 8) * 5 = 40min(8,8)∗5=40。兩指針對應的數字相同,我們可以任意移動一個,例如左指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
此時可以容納的水量爲 \min(6, 8) * 4 = 24min(6,8)∗4=24。由於左指針對應的數字較小,我們移動左指針,並且可以發現,在這之後左指針對應的數字總是較小,因此我們會一直移動左指針,直到兩個指針重合。在這期間,對應的可以容納的水量爲:\min(2, 8) * 3 = 6min(2,8)∗3=6,\min(5, 8) * 2 = 10min(5,8)∗2=10,\min(4, 8) * 1 = 4min(4,8)∗1=4。

在我們移動指針的過程中,計算到的最多可以容納的數量爲 4949,即爲最終的答案。

# cpp
class Solution {
public:
    int maxArea(vector<int>& height) {
        int res = 0;
        int i = 0;
        int j = height.size() - 1;
        while (i < j) {
            int area = (j - i) * min(height[i], height[j]);
            res = max(res, area);
            if (height[i] < height[j]) {
                i++;
            } else {
                j--;
            }
        }
        return res;

    }
};
# python3
class Solution:
    def maxArea(self, height: List[int]) -> int:
        l, r = 0, len(height) - 1
        ans = 0
        while l < r:
            area = min(height[l], height[r]) * (r - l)
            ans = max(ans, area)
            if height[l] <= height[r]:
                l += 1
            else:
                r -= 1
        return ans
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章