Given n non-negative integers a1, a2, …, an , where each represents a point at coordinate (i, ai). n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0). Find two lines, which together with x-axis forms a container, such that the container contains the most water.
Note: You may not slant the container and n is at least 2.
The above vertical lines are represented by array [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue section) the container can contain is 49.
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
首先可以暴力求解,枚举每两个柱子,算他们之间的盛水量,取最大的,时间复杂度: O ( n 2 ) O(n^2) O(n2)
采用双指针法,两个指针分别在首尾,先计算出来此时的水量,然后以下每一步:
- 假如左指针指向的柱子比右指针指向的柱子低,那么左指针右移
- 反之右指针左移
- 更新最大水量
直至两指针相遇。
这个思路在于每次移动指针要移动较低的那个,因为向里移动之后宽度肯定变小,为了能使水量增加,要想办法使最小高度变大,移较低的那个是有可能使水量增加的。反之假如移较高的那个,水量是肯定会减少的。
如何证明最后得出的是最优解?假设存在 [ol,or]
是最优解,但是这一对被扫描的时候漏掉了,也就是说左指针指向 ol
,右指针指向 or
这种情况没有发生,那么也就是说在左指针已经扫过 ol
时,右指针还没扫到 or
,或者再反过来,不失一般性,假设当前左指针指向 ol
,右指针指向 pr
,而 pr
在 or
的右边(也就是右指针还没扫到 or
),此时下一时刻刚好是左指针右移(这样就可以达成条件:漏掉所谓的最优解 ol,or
),什么时候左指针会右移?当 h[ol]<h[pl]
时,此时的水量为 h[ol]*(pl-ol)
,而假设的那个最优解的水量为 min(h(ol),h(or))*(or-ol)
,其中 (or-ol)<(pl-ol)
,并且 min(h[ol],h[or])<h[ol]
,因此这个所谓的最优解是不如 [ol,pl]
的,矛盾!
class Solution {
public:
int maxArea(vector<int>& height) {
int sz=height.size();
int i=0,j=sz-1;
int res=min(height[i],height[j])*j;
while(i<j-1){
if(height[i]<height[j])i++;
else j--;
res=max(res,min(height[i],height[j])*(j-i));
}
return res;
}
};