1.题目
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
2.思路
用双指针来解决这个问题。一个指向容器的左边界(x),一个指向容器的右边界(y),题目说的是盛水,那么只能以(x, y)中最小的作为高了,那么底就是容器两边界的距离,假设用t表示,容器的面积为area = min(x,y)*t 。题目要求的是盛最多水的容器,也就是要找到面积最大的。
起初x指向的是数组起点,y指向的是数组最右边,求此时容器的面积,假设容器最大面积为0,将两个面积相比,记录下最大的。然后移动高最小的那个指针,如果x小于y的话,就x++,如果y<x的话,就y–,然后继续求面积,比较并记录下最大的面积,当两个指针相碰就结束循环了。最终area存储的就是最大的面积。
那么这里就有一个问题了,为什么是移动最高最小的指针?假设x<y,如果移动的是y,此时指针指向y1,两指针之间的距离为t1 。起初面积是min(x,y)*t, 现在面积是min(x,y1)*t1 。已知的是t1<t ,因为x<y,所以min(x,y)=x,而无论y1>=x, 还是y1<x,min(x,y1)都小于或等于x,所以min(x,y1)*t1 < min(x,y)*t 。由此可以得出一个结论,如果移动的是最高的那个指针,得到的面积永远小于原位置的面积,这样就无法找到最大的容器,所以我们选择移动高最小的指针
3.答案
class Solution {
public int maxArea(int[] height) {
//采用双指针的思想,一个代表左边界,一个代表有边界
int l=0;
int r=height.length-1;
int mArea=0; //代表面积
//只有左指针=右指针后才算结束
while(l<r){
int area = Math.min(height[l],height[r])*(r-l);//以最矮的作为高
mArea = Math.max(area,mArea);//记录面积最大的
//每次都找最矮的,让他移动
if(height[l]<height[r]){
l++;
}else{
r--;
}
}
return mArea;
}
}