盛水最多的容器
问题:
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.
翻译
给定n个非负整数a1,a2….,an,其中每个表示一个坐标点(i, ai)。绘制n个垂直线,使i行的两个端点位于(i, ai) 和 (i,0).找到两条线,连同x轴形成一个容器,使容器容纳最多的水。注意:你不能倾斜容器,n至少是2。
示例:
输入:(1,2),(2,3),(3,1),(4,5),(5,4)
输出:8
分析:
很容易想到暴力方法:求出每条竖线和其它每条竖线组成的水桶的面积,然后求出最大的面积即可,很明显,时间复杂度为O(n2)。
对于这道题,还有一种解法。我们假如 i 和 j 分别为给出的x坐标轴的下标,其中i < j。height[i] 和 height[j] 分别为i 和 j 对应的y轴的大小。那么现在容器的面积为f(i,j) = min(height[i], height[j]) * (j - i)。那么对于相邻的直线组成的水桶有如下几种情况。
假如height[i] < height[j]
1.height[ i+1 ] <= height[i],则 f(i + 1, j) = min(height[i - 1], height[j]) * (j - i - 1) = height[i - 1] * (j - i - 1) ,故f(i + 1, j) < f(i, j);
2.height[ i+1] > height[i],则 f(i + 1, j) = height[i] * (j - i - 1), 故f(i + 1, j) < f(i, j);
3.height[j - 1] <= height[j],则f(i, j - 1) = min(height[i], height[j - 1]) * (j - i -1),无法确定 f(i, j - 1) 和 f(i, j) 的大小。
4.height[j - 1] > height[j], 则f(i, j - 1) = height[i] * (j - i -1),故f(i, j - 1) < f(i, j)。
综上 只需判断 f(i, j - 1) 和 f(i, j) 的大小即可。
同理可分析出对于height[i] >= height[j]
只需判断f(i + 1,j) 和 f(i, j) 的大小即可
代码:
public int maxArea(int[] height) {
int l = 0, r = height.length - 1, maxArea = 0;
while (l < r) {
maxArea = Math.max(maxArea, (r - l) * Math.min(height[l], height[r]));
if (height[r] > height[l]) {
r--;
} else {
l++;
}
}
return maxArea;
}