题目描述
给你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
解题思路
该题目是使用贪心算法解题的一个经典案例。
- 首先,不论如何,我们一开始可以使用最边上的两个垂线作为可能的解,真正的解一定在这两个垂线之间。
- 我们进一步选择可行的更优解,一个合理的抉择是放弃当前两个垂线中更短的那一个,然后从该垂线开始向内部的垂线进行搜索,直到找到使得容积更大的垂线。
- 我们可以一直搜寻直到选择的两个垂线相邻,然后在这个寻找的过程中找到的最大容积作为最优解输出。
为什么这样进行搜索可以不忽略其他最优解呢?答案如下:
设当前左边的垂线为第l
根垂线,右边的垂线是第r
根垂线,当前容积是V = (r-l)*min(height[l],height[r])
此时选择更短的一根垂线,不妨设为l
,使得它加一,尝试寻找更优解。这样做可以存在这样的情况,即(r-l-1)*min(height[l+1],heigh[r])>(r-l)*min(height[l],height[r]),即(r-l-1)*height[r或l+1]>(r-l)*height[l]
,因为height[l+1]和height[r]都可能会比height[l]大;否则的话,选择改变r的值的话,得到的V'=(r-1-l)*min(height[l],height[r])
就一定是等于(r-1-l)*height[l]
或者是(r-l-1)乘一个比height[l]更小的数
,不可能得到更大的容积。
代码
class Solution {
public:
int maxArea(vector<int>& height) {
int l = 0;
int r = height.size()-1;
int m = (r-l)*min(height[l],height[r]);
while(l<r)
{
if(height[l]<height[r])
{
l++;
}
else
{
r--;
}
m = max((r-l)*min(height[l],height[r]),m);
}
return m;
}
};