welcome to my blog
LeetCode Top 100 Liked Questions 11. Container With Most Water (Java版; Medium)
题目描述
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.
Example:
Input: [1,8,6,2,5,4,8,3,7]
Output: 49
class Solution {
public int maxArea(int[] height) {
int n = height.length;
int left = 0, right = n - 1;
int max = 0;
while(left<right){
max = Math.max(max, Math.min(height[left], height[right])*(right-left));
if(height[left]<height[right]){
left++;
}else{
right--;
}
}
return max;
}
}
第二次做; 数组无序也能用双指针, 核心: 双指针的移动原则是什么? 舍弃当前边界中更短的边界, 为什么短边可以舍弃? 因为保留短边的话, 另一个指针再怎么移动也只能减少面积, 舍弃一条边相当于舍弃了O(N)种不行的方案; 这样做之所以能够找到最优解, 是因为双指针相当于用O(N)的时间复杂度考虑完了O(N^2)的搜索空间, 见下面的证明;
/*
数组无序, 如何使用双指针? 从两端向中间移动
存水高度取决于两个边界中较低的
*/
class Solution {
public int maxArea(int[] height) {
int n = height.length;
int left=0, right=n-1;
int res = 0;
while(left<right){
//注意求面积时宽度是right-left, 不是right-left+1
int water = (right - left) *(Math.min(height[left], height[right]));
if(water > res)
res = water;
//如何移动柱子? 舍弃当前边界中更短的边界; 并不是说选取下一个更高的边界
if(height[left]<height[right])
left++;
else{
right--;
}
}
return res;
}
}
第一次做, 双指针, 每次移动都舍弃当前的短边, 为什么? 因为保留短边的话, 高最高就是短边的长度, 同时宽度会随着指针移动逐渐变小, 所以面积会变小; 只有舍弃当前的短边才有可能找到更长的边, 使得面积增大
class Solution {
public int maxArea(int[] height) {
int left=0, right=height.length-1;
int max = 0;
while(left<right){
max = Math.max(max, (right - left) * Math.min(height[left], height[right]));
//舍弃短边
if(height[left]<height[right])
left++;
else
right--;
}
return max;
}
}
第一次做, 暴力
//暴力
class Solution {
public int maxArea(int[] height) {
int max=0;
for(int i=0; i<height.length; i++){
for(int j=i+1; j<height.length; j++){
max = Math.max(max, (j-i)*Math.min(height[i], height[j]));
}
}
return max;
}
}
LeetCode双指针法证明
为什么短边可以舍弃? 因为保留短边的话, 另一个指针再怎么移动也只能减少面积
I know that some people are still having a hard time understanding this proof, but please re-read original proof a few times.
Here is my example hope it helps.
[4 (left) , 9, 12, 7 , 8, 14 (right) ] --------> this array is indexed from 1 to 6 and we looks at left and right and compare the value
So eliminate all pairs of index [1,2], [1,3],[1,4],[1,5] <- here the index[] means possible windows of solutions (4,9), (4,9,12), (4,9,12,7)...
Why? area of window [1,6] = (6 - 1) * MIN(4, 14) = 20
all the windows that have [1,2...5] even if all the numbers on the right are changed to infinity must be less than 20.
EX:
(5-1) * min(4, infinity) < 20 for all right indicies less than 6.
So this means its ok to exclude all windows starting with index 1
If you apply this at each step over and over again you can get an O(n) algorithm.
Hope this helps.