给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
示例

1. 暴力解法:
- 遍历i,用右边的j去和它组成容器(为什么用右边,因为左边是i和j 指针对称调换的结果)
- 每次算出的面积和最大值比较,取较大的。
private static int maxArea(int[] arr,int n){
int maxArea = 0;
for(int i = 0; i < n ; i++){//这里注意
for(int j =i+1;j < n;j++){
int w = j-i;
int h = Math.min(arr[i],arr[j]);
int area = w*h;
maxArea = Math.max(area,maxArea);
}
}
return maxArea;
}
2. 左右夹逼算法---又叫左右边界向中间收敛方法,类似题目都可以使用
- 这里使用的原理是对于指定的i,j,对应的面积S(i,j)
- 如果对应的高度h[i] < h[j] ,那么j不用收敛,因为i是木桶原理的较小那个,j收敛也改变了木桶的最小高度。所以j收敛不可能找到更大面积的。
- 所以i收敛,i++,并计算此时的面积,和最大面积比较
- 然后继续比较h[i]和h[j]的高度,根据木桶原理,较小的继续收敛
- 知道i和j相遇,就找到了最大面积;
- 关于这个理论的证明以及动画链接:
代码如下:
private static int maxArea2(int[] arr,int n){
int maxArea = 0;
System.out.print("max2");
for(int i = 0,j=n-1; i < j ; ){
int w = j-i;
int h = Math.min(arr[i],arr[j]);
maxArea = Math.max(w*h,maxArea);
if(arr[i] <= arr[j]){
i++;
}else{
j--;
}
}
return maxArea;
}
、