Question:
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,a3……,每个非负整数代表一个坐标(i,ai),以这个坐标为端点向x轴作垂线,那么这条线的两个端点就是(i,ai)和(i,0)。找到两条线,连同x轴形成一个容器,使容器容纳最多的水。
Note:你不能倾斜容器 && n至少是2
Answer:
题目就是要找到容器最大盛水量。
第一种方法:两层循环,一直找一直找……(提交超时)
public int maxArea(int[] height) {
int len = height.length;
int x,y;
int maxWater = 0;
int tmpWater = 0;
for(x=0;x<len;x++){
for(y=x;y<len;y++){
tmpWater = Math.min(height[x],height[y])*(y-x);
maxWater = Math.max(maxWater,tmpWater);
}
}
return maxWater;
}
第二种方法:
我们可以设置两个指针left和right,分别从数组左右两端向中间开始查找,当left>=right时,查找结束。
当left和right指针指向两个不同的边时,我们计算他的容器最大盛水量,然后移动指针,那么如何确定是移动left指针还是right指针?由于指针是向中间移动的,所以不管是left指针移动还是right指针移动,容器的底都会减小1,那么为了使得容器的盛水量增加,我们需要不断地增加高度,这时我们需要判断一下当前我们的容器左右边的长度,只有淘汰较短的那条边,才有可能增加当前边的高度(虽然也有可能减小,但是没关系,减小的话我们已经把最大值保存下来了),使得容器的盛水量进一步增大。
因此当height[left] < height[right]时,明显left指针指示的边长度要小于right指针指示的边,因此left++。反之right++;
public int maxArea(int[] height){
int left = 0;
int right = height.length-1;
int maxWater = 0;
int tmp_water = 0;
while(left<right){
tmp_water = Math.min(height[left],height[right])*(right-left);
if(height[left]<height[right]){
left++;
}else{
right--;
}
maxWater = Math.max(maxWater,tmp_water);
}
return maxWater;
}
(而使用height[left+1]和height[right-1]判断哪个指针需要移动的想法:当指针的下一条边更大的时候当然要走向下一条更大的边……这种思路是不正确的,因为这样有可能会错过最大的那条边,会使你丢失正确答案
//错误代码
public int maxArea(int[] height){
int left = 0;
int right = height.length-1;
int maxWater = 0;
int tmp_water = 0;
while(left<right){
tmp_water = Math.min(height[left],height[right])*(right-left);
if(height[left+1]>height[right-1]){
left++;
}else{
right--;
}
maxWater = Math.max(maxWater,tmp_water);
}
return maxWater;
}
Input: [1,2,4,3]
Output: 3
Expected: 4
最大盛水量是4,但是输出却是3,为什么?因为当left=0,right=3时,他们的下一条边4>2,因此,right–,这一移动不要紧,直接就错过了最大盛水量容器的一条边)。