leetcode 11 題解:python3@ 官方題解_暴力法_雙指標法

娃哈哈店長發表於2020-02-07

leetcode解題得的原始碼,解題思路在程式碼的註釋裡。

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

題目原址:https://leetcode-cn.com/problems/container...
使用:vscode

Brute-force/暴力法

透過遞迴的思想來用暴力法遍歷所有資料
程式碼:

#
# @lc app=leetcode.cn id=11 lang=python3
#
# [11] 盛最多水的容器
#

# @lc code=start
from typing import List

class Solution:
    def __init__(self):
        self.maxContent = 0

    def force(self, height: List[int]) -> int:
        # print(len(height))
        # get the last one & del it
        last = height.pop()
        for key,value in enumerate(height):
            # Short board effect, get the minimm value between the last one & current value
            tmp = min(last,value)*(len(height)-key)
            self.maxContent = max(tmp,self.maxContent)
            # print(self.maxContent)
        if len(height) == 1:
            return self.maxContent
        else:
            #Iterativly call self.force() with new params height
            return(self.force(height))

    def maxArea(self, height: List[int]) -> int:
        return {
            0 :lambda height :self.force(height),
        }[0](height)
# @lc code=end

if __name__ == "__main__":
    solve = Solution()
    print(solve.maxArea([1,8,6,2,5,4,8,3,7]))

提交效果:

  • 42 / 50 個透過測試用例
  • 狀態:超出時間限制

複雜度分析:

  • time complexity :$O(n^{2})$ ,計算所有$\frac{n(n-1)}{2}$ 種高度組合的面積
  • space complexity :$O(1)$,使用恆定的self.maxContent空間

Double-pointer/雙指標法

傳統方法,兩個指標,分別指向the first onethe last one,另外使用self.maxContent來儲存最大的面積。

最初我們考慮由最外圍兩條線段構成的區域。現在,為了使面積最大化,我們需要考慮更長的兩條線段之間的區域。如果我們試圖將指向較長線段的指標向內側移動,矩形區域的面積將受限於較短的線段而不會獲得任何增加。但是,在同樣的條件下,移動指向較短線段的指標儘管造成了矩形寬度的減小,但卻可能會有助於面積的增大。因為移動較短線段的指標會得到一條相對較長的線段,這可以克服由寬度減小而引起的面積減小。

兩個指標相互靠近時,矩形的底是變小的,所以只有高變大才有可能面積變大,所以讓短的向長的那個靠近。

程式碼:

#
# @lc app=leetcode.cn id=11 lang=python3
#
# [11] 盛最多水的容器
#

# @lc code=start
from typing import List

class Solution:
    def __init__(self):
        self.maxContent = 0

    def burte_force(self, height: List[int]) -> int:
        # print(len(height))
        # get the last one & del it
        last = height.pop()
        for key,value in enumerate(height):
            # Short board effect, get the minimm value between the last one & current value
            tmp = min(last,value)*(len(height)-key)
            self.maxContent = max(tmp,self.maxContent)
            # print(self.maxContent)
        if len(height) == 1:
            return self.maxContent
        else:
            #Iterativly call self.burte_force() with new params height
            return(self.burte_force(height))

    def double_pointer(self, height: List[int]) -> int:
        i, j= 0, len(height) - 1
        while i < j:
            # the pointers approach eacher other, their distance becomes smaller, so the only when the short one approach the long one the area can be larger.
            if height[i] < height[j]:
                self.maxContent = max(self.maxContent, height[i] * (j - i))
                # the left pointer move right
                i += 1
            else:
                self.maxContent = max(self.maxContent, height[j] * (j - i))
                # the right pointer move left
                j -= 1
        return self.maxContent
    def maxArea(self, height: List[int]) -> int:
        return {
            0 :lambda height :self.burte_force(height),
            1 :lambda height :self.double_pointer(height),
        }[1](height)
# @lc code=end

if __name__ == "__main__":
    solve = Solution()
    print(solve.maxArea([1,8,6,2,5,4,8,3,7]))

提交效果
Accepted

  • 50/50 cases passed (148 ms)
  • Your runtime beats 66.95 % of python3 submissions
  • Your memory usage beats 50.48 % of python3 submissions (14.6 MB)

複雜度分析:

  • time complexity : $O(n)$ ,雙指標遍歷一次底邊寬度$N$。
  • space complexity :$O(1)$ ,使用恆定的self.maxContent空間
本作品採用《CC 協議》,轉載必須註明作者和本文連結
文章!!首發於我的部落格Stray_Camel(^U^)ノ~YO

相關文章