https://leetcode-cn.com/problems/container-with-most-water/
分析
这道题乍一看与接雨水那道题很像,但那题是求总共能接到的水量,这题则是要求两个边界组成的容器的最大容量。暴力解法是枚举所有的左右边界,计算其容器的容量,再取最大值,时间复杂度为 O ( n 2 ) O(n^2) O(n2),超时了。
解法
这道题要用双指针来解答, 如果给你双指针这个提示的话,你应该会容易想到每次移动更矮的那个边界会是正确的做法,但是怎么证明呢?
对于所有的这些线,它们都有可能作为一个容器的边界。设最左的线高度为
x
x
x,最右的线高度为
y
y
y,线之间间隔一共为
t
t
t,则
x
x
x和
y
y
y组成的容器的容量为:
m
i
n
(
x
,
y
)
∗
t
min(x,y)*t
min(x,y)∗t。
我们假设
x
<
=
y
x <= y
x<=y,如果移动
y
y
y的话,必只能向左移动,新的线高度为
y
1
y_1
y1,容易知道
m
i
n
(
x
,
y
1
)
<
=
m
i
n
(
x
,
y
)
min(x,y_1) <= min(x,y)
min(x,y1)<=min(x,y)而新的容器容量为
m
i
n
(
x
,
y
1
)
∗
(
t
−
1
)
<
m
i
n
(
x
,
y
)
∗
t
min(x,y_1) * (t-1) < min(x,y) * t
min(x,y1)∗(t−1)<min(x,y)∗t,所以,不论怎么移动右边界,组成的容器容量都是会变小的,换句话说,以
x
x
x为边界的最大容量的容器已经找到了,
x
x
x已经没有必要出现在之后的讨论中,所以我们移动左边界,并将
x
x
x这条线视为消失了。
代码
class Solution {
public:
int maxArea(vector<int>& height) {
int result = 0;
int left = 0, right = height.size() - 1;
while (left < right) {
result = max(result, min(height[left], height[right]) * (right - left));
if (height[left] < height[right]) left++;
else right--;
}
return result;
}
};
复杂度分析
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)。