【Leetcode】11.盛水最多的容器

11 盛水最多的容器

题目:
给你 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

思路:双指针法
水的面积为左柱子和右柱子中高度的最小值乘上两个柱子之间的距离。最开始将左右柱子分别设为最左边和最右边的柱子,此时两柱子间的距离是最大的,但两柱子的高度未必是。记下当前的面积,之后不断将两柱子向内移动,并同时更新最大面积。当两柱子相遇时,代表所有有可能产生最大面积的柱子组合都被尝试完毕,此时返回最大面积。

但两柱子具体是怎样移动的呢?考虑将两柱子向内移动意味着两根柱子之间的距离不断地缩小,所以要达到最大面积,必然寄希望于移动后两根柱子中的最小值大于当前两柱子中的最小值。如果较短的柱子不移动,两柱子高度的最小值则不变化,但两柱子间距变小了,这种情况肯定不可能得到更大的面积,所以这种情况就不必尝试。

每次将两柱子中较短的那个柱子向内移动,较长的柱子不移动。这种情况移动后可能产生更大面积,也可能不会产生更大面积。但每一次尝试都将当前的面积与之前保存的最大面积比较,并更新最大面积,这样就可以通过不断尝试获得最大面积。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public int maxArea(int[] height) {
int left = 0;
int right = height.length - 1;
int max_area = 0;
while(left < right){
int cur_area = Math.min(height[left],height[right]) * (right - left);
max_area = Math.max(max_area, cur_area);
if(height[left] < height[right])
left++;
else
right--;
}
return max_area;
}