给定 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
class Solution:
def maxArea(self, height: List[int]) -> int:
"""
1.暴力求解
for i in range(n):
for j in range(n):
l = x[i]-x[j]
h = min(height[i],height[j])
max_s = max(l * h,max_s)
return max_s
2.双指针法
"""
n = len(height)
l_left = 0
l_right = n-1
max_s = 0
while l_left < l_right:
h_l = height[l_left]
h_r = height[l_right]
s = (l_right - l_left) * (min(h_l,h_r))
max_s = max(s,max_s)
if h_l < h_r:
l_left += 1
else:
l_right -= 1
return max_s
优化后,用max和min会减慢速度
class Solution:
def maxArea(self, height: List[int]) -> int:
i, j, res = 0, len(height) - 1, 0
while i < j:
if height[i] < height[j]:
res = max(res, height[i] * (j - i))
i += 1
else:
res = max(res, height[j] * (j - i))
j -= 1
return res
'''
作者:jyd
链接:https://leetcode-cn.com/problems/container-with-most-water/solution/container-with-most-water-shuang-zhi-zhen-fa-yi-do/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
'''
证明
原文链接
0,1,2...指高低。s()=h*(x方向距离)
将0,1,2.换为任意值皆成立
用h(i)表示第i条线段的高度,S(ij)表示第i条线段和第j条线段圈起来的面积。
可知 h(0) < h(7),从而S(07) = h(0) * 7。
所以我们应该选(1,7)
分析若选(0,6)会有什么情况:
有S(06) = min(h(0), h(6)) * 6。
当h(0) <= h(6),有S(06) = h(0) * 6;
当h(0) > h(6),有S(06) = h(6) * 6,S(06) < h(0) * 6。
由此可知,S(06)必然小于S(07)。
递推下去,每次被舍弃掉的子节点必定小于父节点。所以不存在遗失最优解的情况。
在选中的子节点中寻找是否有比父节点 / 父节点的父节点 / 父节点的*大的点。