赞
踩
来源:LeetCode
难度:中等
问题详情:
给定一个长度为 n
的整数数组 height
。有 n
条垂线,第 i
条线的两个端点是 (i, 0)
和 (i, height[i])
。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
**说明:**你不能倾斜容器。
示例1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示意图如下所示,图片来源:力扣。
示例2:
输入:height = [1,1]
输出:1
在真正开始介绍各种算法前,先以表格形式展示各自的时间复杂度和空间复杂度,其中 N N N表示列表 h e i g h t height height的长度。
算法 | 时间复杂度 | 空间复杂度 |
---|---|---|
双指针 | O ( N ) O(N) O(N) | O ( 1 ) O(1) O(1) |
为什么上述流程能够找到最优解呢?
接下来就证明这种方案的合理性。
首先假设头尾指针相距为
t
t
t,并且假设
h
e
i
g
h
t
[
h
e
a
d
]
<
h
e
i
g
h
t
[
t
a
i
l
]
height[head]<height[tail]
height[head]<height[tail],则面积
a
r
e
a
=
t
×
h
e
i
g
h
t
[
h
e
a
d
]
area=t×height[head]
area=t×height[head]
假设移动最大者,那么
t
2
=
t
−
1
<
t
t_2=t-1<t
t2=t−1<t,因为高取决于两边的最短边,因此
因此新的高
h
t
2
h_{t_2}
ht2必然是
≤
h
e
i
g
h
t
[
h
e
a
d
]
≤height[head]
≤height[head]的,所以新的面积
a
r
e
a
2
=
t
2
×
h
t
2
≤
a
r
e
a
area_2=t_2×h_{t_2}≤area
area2=t2×ht2≤area.
所以可以看出,移动两者中的最长者必然会导致面积变小;同时也可以进一步想到,无论这个尾指针怎么往内部移动,都不会找到一个更大面积的情况。
也就是说以这个最左边为一边的除了当前 a r e a area area这个情况外的其它情况都不可能是最优解。
所以我们需要记录当前的面积,并移动最左边的指针。
也就是移动最长边必然会导致更小或者不变,移动最短边则有可能会变好。
通过不断的这样筛选的过程,我们其实仍然是遍历了所有可能,只不过那些被淘汰的是隐式地。
def myAtoi(s: str) -> int:
n = len(height)
head = 0
tail = n - 1
# 分别对比左右指针指向的数,最大的一方指针保持不懂,另一方向中间移动
max_area = 0
while head != tail:
if height[head] > height[tail]:
area = (tail - head) * height[tail]
tail -= 1
else:
area = (tail - head) * height[head]
head += 1
max_area = max(max_area, area)
return max_area
对于时间复杂度,因为首尾指针合在一起指向了所有数组的数,所有时间复杂度为 O ( N ) O(N) O(N)
空间复杂度, O ( 1 ) O(1) O(1)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。