leetcode
leetcode解题得的源码,解题思路在代码的注释里。
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
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 one和the 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 协议》,转载必须注明作者和本文链接