leetcode 11 题解:python3@ 官方题解_暴力法_双指针法
leetcode
leetcode解题得的源码,解题思路在代码的注释里。
- 我的leetcode主页https://leetcode-cn.com/u/boywithacoin_cn/
- 我的个人博客https://boywithacoin.cn/
- github_所有源码网址https://github.com/Freen247/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 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 协议》,转载必须注明作者和本文链接
嗯, 也许点数不是只有9点, 也许是10000个点, 还有不同的排列组合, 我想简单了.
我用随机数生成了一个一万笔的列表
结果你的只要5ms, 我的要22ms, 果真如此
148 ms ?? passed ??
我上传了一个, 每次执行代码的执行用时都不一样, 偏差太大了.
比较了一下你的代码和我的代码, 我的快些, 4 ~ 32 ms, 但是提交结果都是超出时间限制, 不知时间限制是多少?
而且怎么可能是ms级的 ? CPU有这么慢 ? 应该是μs级的吧. 我是这么测试的, 结果是
0:00:00.000013 (我的)
0:00:00.000067(你的)