[leetcode 11] 盛最多水的容器(Python 雙指針)

題目描述

給你 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]
輸出:49

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/container-with-most-water


解題思路

思路一:雙指針

容納的水量是由:兩個指針指向的數字中較小值 * 指針之間的距離決定。

先從題目示例開始解釋雙指針算法的操作過程:
題目輸入的數組爲:

[1, 8, 6, 2, 5, 4, 8, 3, 7]

首先左右指針分別指向數組左右兩端,此時可以容納的水量爲:min(1,7)8=8\min(1,7)*8=8
然後需要移動左右指針中對應的數較小的那個指針。
移動後變成了:

[1, 8, 6, 2, 5, 4, 8, 3, 7]

此時可以容納的水量爲min(8,7)7=49\min(8,7)*7=49

再移動數字小的右指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]

此時可以容納的水量爲min(8,3)6=18\min(8,3)*6=18

再移動數字小的右指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]

此時可以容納的水量爲min(8,8)5=40\min(8,8)*5=40

兩指針對應數字相同,選擇其中一個。比如移動左指針:

[1, 8, 6, 2, 5, 4, 8, 3, 7]

此時可以容納的水量爲min(6,8)4=24\min(6,8)*4=24
繼續移動左指針,發現一直比右指針小所以一直移動到兩指針重合。過程中對應的水量爲:min(2,8)3=6\min(2,8)*3=6min(5,8)2=10\min(5,8)*2=10min(4,8)1=4\min(4,8)*1=4
所以,最多可容納的水量爲49。

正確性證明:

雙指針代表可以作爲容器邊界的所有位置的範圍。一開始雙指針指向數組的左右邊界表示數組中所有位置都可以作爲容器的邊界。然後每次將對應數字較小的指針往另一個指針的方向移動,就表示這個指針不可能當容器的邊界了。最後的答案就是每次以雙指針爲左右邊界計算出的容量中的最大值。(詳細證明參見官方題解)

- 複雜度分析

  1. 時間複雜度:O(N)O(N),雙指針總計最多遍歷整個數組一遍。
  2. 空間複雜度:O(1)O(1),只需要額外的常數級別的空間。

代碼實現

雙指針:

class Solution(object):
    def maxArea(self, height):
        start, end = 0, len(height)-1
        maxwater = 0
        while start < end:
            maxwater = max(maxwater,(end - start) * min(height[start], height[end]))
            if height[start] <= height[end]:
                start = start + 1  
            else:
                end = end - 1

        return maxwater

Tips

  1. 雙指針出現的又一次,多練才能出直覺。

Author:ChierAuthor: Chier

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章