11.盛最多水的容器 ------ LeetCode Hot100 ------ JavaScript版
·

算法步骤
-
初始化:左指针在数组开头,右指针在数组末尾
-
循环计算:当左指针 < 右指针时
-
计算当前左右指针围成的面积:
(距离) × (较矮的高度) -
更新最大面积
-
移动较矮的那一边指针(因为移动较高的那边不会增加面积)
-
关键逻辑
-
面积计算:
(right - left) × min(height[left], height[right]) -
指针移动策略:总是移动较矮的那一边
-
因为容器的盛水量由较矮的那边决定
-
移动较矮的指针有可能找到更高的边界,从而增加面积
-
移动较高的指针只会让面积不变或减小
-
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
//贪心思想上看:我们要找到两根最高的 两根间距离最长的
//如果只找最高的 考虑失效的情况:[2,4,5,8,3] --->选择5,8 容纳了5的水 但实际最优是4,3 容纳9的水
ans = 0;
max = 0;
left = 0;
right = height.length - 1;
while(left<right){
ans = (right-left) * Math.min(height[left],height[right]);
max = Math.max(ans,max);
if(height[left]<height[right])
left++;
else
right--;
}
return max;
};
数据测试逐步解析
测试数据:[1,8,6,2,5,4,8,3,7]
| 步骤 | left | right | 高度[left] | 高度[right] | 距离 | 较矮高度 | 当前面积 | 最大面积 | 移动方向 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 8 | 1 | 7 | 8 | 1 | 8 | 8 | left++ |
| 2 | 1 | 8 | 8 | 7 | 7 | 7 | 49 | 49 | right-- |
| 3 | 1 | 7 | 8 | 3 | 6 | 3 | 18 | 49 | right-- |
| 4 | 1 | 6 | 8 | 8 | 5 | 8 | 40 | 49 | left++ 或 right-- |
| 5 | 2 | 6 | 6 | 8 | 4 | 6 | 24 | 49 | left++ |
| 6 | 3 | 6 | 2 | 8 | 3 | 2 | 6 | 49 | left++ |
| 7 | 4 | 6 | 5 | 8 | 2 | 5 | 10 | 49 | left++ |
| 8 | 5 | 6 | 4 | 8 | 1 | 4 | 4 | 49 | left++ |
最终结果:49(对应 left=1, right=8 时的容器)
简单案例:[1,2,4,3]
| 步骤 | left | right | 高度 | 距离 | 较矮高度 | 当前面积 | 最大面积 | 移动方向 |
|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 3 | 1,3 | 3 | 1 | 3 | 3 | left++ |
| 2 | 1 | 3 | 2,3 | 2 | 2 | 4 | 4 | left++ |
| 3 | 2 | 3 | 4,3 | 1 | 3 | 3 | 4 | right-- |
最终结果:4(对应 left=1, right=3 时的容器)
为什么移动较矮的指针?
考虑两种情况:
-
如果移动较高的指针:距离减小,高度不会超过当前较矮的高度,面积必然减小
-
如果移动较矮的指针:距离减小,但可能找到更高的边界,面积有可能增加
时间复杂度
-
O(n):每个指针最多移动n次
-
O(1):只使用了常数空间
更多推荐

所有评论(0)