题目描述
给定 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.底边长 2.短边高度 ,设左右两个指针 i j,分别扫描。一直移动短边,即 i高度 < j时, i 右移 ; i 高度 > j 时,j 左移。
代码
class Solution {
public:
int maxArea(vector<int>& height) {
int maxArea = 0,l = 0,r = height.size() - 1;
while(l < r){
maxArea = max(maxArea,min(height[l],height[r]) * (r - l));
if(height[l] < height[r]){
l++;
}
else
r--;
}
return maxArea;
}
};
为什么不会错过最优解?
当前容积为A = (j - i) * min( h(i),h(j) ),因为短边是容积的影响因素,所以如果长边的下一个更长,移动长边,对容积没有影响。如果下一个更短,一定不是最优解。移动短边才会出现最优解。
虽然移动矮指针以后会可能出现更大的面积,从而放弃了移动高的指针,但是没准虽然现在 移动高的指针不能增加但是以后以这个为基准会演变出最大的面积?
我们担心如果高指针 j 的下一个 n 更高,不移动 j 会不会错过这个n边。也就是说,我们会错过i 到 n之间的一段面积,而这个面积会成为最大值?
假设目前状况如下:
假设 i ~ n 间存在一个 m ,使得 m ~n的面积最大.
-
H
m
<
=
H
j
H_m <= H_j
Hm<=Hj时:
m n mn mn 的面积一定小于等于 m j mj mj, m n mn mn并不是最大值,与题设不符。
-
H
m
>
H
j
H_m > H_j
Hm>Hj时
低指针 i 移动到 m 时,因为 H m > H j H_m > H_j Hm>Hj,所以高指针此时变为m,j指针一定会向左移动至n,不会错过这个解(无论 H n H_n Hn和 H m H_m Hm的关系如何)。