11. 盛最多水的容器
题目介绍
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
示例
思路梳理
分析
我们先从题目中的示例开始,一步一步地解释双指针算法的过程。稍后再给出算法正确性的证明。
题目中的示例为:
[1, 8, 6, 2, 5, 4, 8, 3, 7]
^ ^
在初始时,左右指针分别指向数组的左右两端,它们可以容纳的水量为 \min(1, 7) * 8 = 8min(1,7)∗8=8。
此时我们需要移动一个指针。移动哪一个呢?直觉告诉我们,应该移动对应数字较小的那个指针(即此时的左指针)。这是因为,由于容纳的水量是由
两个指针指向的数字中较小值 * 指针之间的距离
两个指针指向的数字中较小值∗指针之间的距离
决定的。如果我们移动数字较大的那个指针,那么前者「两个指针指向的数字中较小值」不会增加,后者「指针之间的距离」会减小,那么这个乘积会减小。因此,我们移动数字较大的那个指针是不合理的。因此,我们移动 数字较小的那个指针。
代码
题解1
双指针
class Solution:
def maxArea(self, height: List[int]) -> int:
h_len = len(height)
# 左指针和右指针
lp = 0
rp = h_len-1
max_v = 0
while lp<rp:
max_v = max(min(height[lp],height[rp])*(rp-lp),max_v)
if height[lp]<height[rp]:
lp+=1
else:
rp-=1
return max_v
题解2
暴力解法,超时容易
class Solution:
def maxArea(self, height: List[int]) -> int:
h_len = len(height)
max_v = 0
for i in range(h_len-1):
j = i + 1
while j < h_len :
v = min(height[i], height[j]) * (j - i)
max_v = max(v, max_v)
j+=1
return max_v
总结
复杂度分析
时间复杂度:O(N)O(N),双指针总计最多遍历整个数组一次。
空间复杂度:O(1)O(1),只需要额外的常数级别的空间。