LeetCode 11題盛最多水的容器

Problem 11 盛最多水的容器

題目

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

說明:你不能傾斜容器,且 n 的值至少爲 2。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/container-with-most-water
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
圖中垂直線代表輸入數組 [1,8,6,2,5,4,8,3,7]。在此情況下,容器能夠容納水(表示爲藍色部分)的最大值爲 49。

示例:

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

分析以及解決辦法

“”"
盛最多水的容器
如果用最暴力的方法,那就是計算任意兩個數作爲答案可以容納的水,然後
找到最大值作爲結果輸出,這樣的時間複雜度爲 n²,結果運行出來的結果是時間超時,所以要尋找更優速度

然後我發現了一個規律,左邊的那個值,如果大小再下降,那麼就直接跳過就可以了,右邊的那個值,如果大小再
上升,那麼這個值也可以跳過就行了。可以仔細想想是不是這樣。 可是結果還是時間超時,媽的我太蠢了

看到別人說的雙指針法,發現上面的解法已經有點接近了,但還是不如雙指針來的簡單,上面的複雜度還是n²的複雜度
雙指針法:也就是在起始端和末端都安排一個指針,然後兩個指針分別根據情況來向內側移動,不斷計算容器大小來
更新最大值,這樣指針交錯就可以結束遍歷了,這樣的話時間複雜度就只有 O(n)了
這次方法終於時間通過了,代碼中還可以詳細添加判斷條件,如果右移的值還沒有左邊大,那麼就不用計算本次容器值了,同樣的
如果左移的值還沒有右邊大,那也不用計算本次容器值了。因爲不可能大於當前的最大值

“”"

way 1

from typing import List

# class Solution:
#     def maxArea(self, height: List[int]) -> int:
#         max = 0
#         for i in range(len(height)-1):
#             # 用冒泡排序的方式來分別計算容器體積
#             for j in range(i+1,len(height)):
#                 num = min(height[i], height[j]) * (j-i)
#                 if num > max:
#                     max = num
#         return max

way 2

from typing import List
# class Solution:
#     def maxArea(self, height: List[int]) -> int:
#         max = 0
#         for i in range(len(height)-1):
#             # 如果它比左邊的數小,那麼直接跳到下次循環
#             if i > 0 and height[i] < height[i-1]:
#                 continue
#             for j in range(i+1,len(height)):
#                 # 如果它右邊的數比它大,那麼這個數也可以直接跳過了
#                 if j < len(height)-1 and height[j] < height[j+1]:
#                     continue
#                 num = min(height[i], height[j]) * (j-i)
#                 if num > max:
#                     max = num
#         return max

way3

from typing import List
class Solution:
    def maxArea(self, height: List[int]) -> int:
        left = 0
        right = len(height)-1
        max = min(height[0], height[len(height) - 1]) * (right - left)
        while left < right:
            # 循環終止條件如上
            if height[left] < height[right]:
                # 左邊的值限制了容器大小,則左指針往右移動,並且可以加上條件,如果右移的值
                # 如果右移的值還沒有左邊大,那麼就不用計算本次容器值了,
                left = left +1
                # while height[left] < height[left+1] and (left+1)<right:
                #     left = left +1
                num = min(height[left], height[right]) * (right-left)
                if num>max:
                    max = num
            else:
                # 右邊的值限制了容器大小,右指針往左移動,並且加上條件,如果左移的值
                # 如果左移的值還沒有右邊大,那也不用計算本次容器值了。因爲不可能大於當前的最大值
                right = right -1
                # while height[right] > height[right-1] and (right-1)>left:
                #     right = right -1
                num = min(height[left], height[right]) * (right - left)
                if num > max:
                    max = num
        return max

a = [1,8,6,2,5,4,8,3,7]
solu = Solution()
answer = solu.maxArea(a)
print(answer)

總結

還是得多刷題,題目感覺不難,但是想要通過或者說找到簡便答案有時候還是得多刷題,才能漸漸熟悉。
fighting

發佈了53 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章