题目:
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.
思路:
如图所示,我们从1开始到7结束。
首先,明白一点:1的值比7的值小,那么,以1开头的所有面积,不可能比从1到7的面积还大。
如果1 的值比7的值大,那么,从7到除1之外的其他所有点的面积不可能比到1的面积大。
所以,该思想很巧妙的利用了能够从两边向中间靠拢的思路进行构想。
即,设定left为左下标,right为右侧下标。那么,如果height[left]<height[right],那么left向右移动。否则,right向左移动。
但是有人会问,(1~7)算完了,那么不算1到6或者1到5或者其他的了么?难道就直接把1可以舍弃了么?
答案是可以的。从1到7的面积已经算过,如果某个矩形里有以1为边界的,那么,该矩形不可能比1~7的矩形更大。
因此,1的参与已经完成,有1参与的可能的最大值已经记录在案(1~7),但是要记住,之所以能够舍弃1,是因为1的值比7的值小。
如果反之,那么舍弃的将是7.
再分析一下,以上1的使命结束,那么走到2和7.对于2来说,2之前的都已经不用考虑,因为,如果2和1形成矩阵,则肯定不会比7和1的矩阵大。
证明:假设2的值大于1的值,则以1的值为准,面积显然小于1和7的矩阵;假设2的值小于1的值,那么不光从长上面,1到2小于1到7,从高的角度来讲,更是小于1的高度。
因此,不管2的值多大,都不用考虑2之前的值。所以,之后的所有计算都从2到7之间。
该方法非常巧妙,得到了O(n)的复杂度,非常经典。
AC代码:
public int maxArea(int[] height) {
if(height==null || height.length==0)
return 0;
int left = 0;
int right = height.length-1;
int max = 0;
while(left<right){
int area = (right-left)*Math.min(height[left],height[right]);
max = max<area?area:max;
if(height[left]<height[right])
left++;
else
right--;
}
return max;
}