【LeetCode 11】盛最多水的容器:双指针从两端逼近,移动短板才有意义(JS)

目标:任选两条竖线 i、j(i<j),容器面积
area = (j - i) * min(height[i], height[j]),求最大值。
约束:2 <= n <= 1e5,0 <= height[i] <= 1e4。
思路(两端逼近 + 只移动短板)
-
用两个指针
l=0、r=n-1。 -
当前面积
A = (r-l) * min(h[l], h[r]);更新答案。 -
关键:只移动较短的那一侧:
-
若
h[l] < h[r]⇒l++ -
若
h[l] > h[r]⇒r-- -
若相等 ⇒ 随便移动一侧(移动任一短板都不亏)
-
直觉:宽度每次都减 1,要想面积能变大,只能期待短板高度变高;移动长板只会让宽度变小,短板不变,高度上限仍由短板决定,面积只会更小或相等。
代码(JavaScript)
/**
* @param {number[]} height
* @return {number}
*/
var maxArea = function(height) {
//设置双指针,左指针往右走,右指针往左走
let l=0;
let r=height.length-1;
//存放最大容积的
let max_rj=0;
while(l<r){
let rj=(r-l)*Math.min(height[l],height[r]);
max_rj=Math.max(max_rj,rj)
//只移动短板,因为如果移动长板,会造成短板找更短板的组合
if (height[l]<height[r]){
l++;
}
else{
r--;
}
}
return max_rj;
};
为什么一定移动短板(正确性说明)
设当前两端为 i、j,且 h[i] <= h[j],面积 A = (j-i)*h[i]。
-
如果移动长板到
j' = j-1:新宽度j'-i < j-i,新高度仍被h[i]限制(因为min(h[i], h[j']) <= h[i]),
所以新面积A' <= (j-i-1)*h[i] < (j-i)*h[i] = A,不会更大。 -
因此,只有移动短板(
i' = i+1)才有可能把“短板高度”抬高,从而抵消宽度的减少并获得更大面积。
一句口诀:“面积由短板定,想变大先抬短板;宽度只能减,长板别动它。”
复杂度
-
时间:O(n),双指针最多各走 n 步。
-
空间:O(1)。
常见坑
-
❌ 同时移动两边 → 可能跳过最优解。
-
❌ 等高时纠结移动哪边 → 移任意一侧都可;也可以两边都移动一次,但没必要。
-
❌ 用乘法时语言整型溢出(JS 没问题,但 C++/Java 用
long/long long)。 -
❌ 误把“雨水”那题(接雨水)当成同一道题:那题要前缀/后缀最高或单调栈,这题不是。
对比:暴力 O(n²)(仅作参考,不建议提交)
function maxAreaBrute(height) {
let ans = 0;
for (let i = 0; i < height.length; i++) {
for (let j = i + 1; j < height.length; j++) {
ans = Math.max(ans, (j - i) * Math.min(height[i], height[j]));
}
}
return ans;
}
测试用例:
console.log(maxArea([1,8,6,2,5,4,8,3,7])); // 49
console.log(maxArea([1,1])); // 1
console.log(maxArea([4,3,2,1,4])); // 16
console.log(maxArea([1,2,1])); // 2
console.log(maxArea([1,2,4,3])); // 4
小结
双指针从两端向中间收缩;每一步只移动短板;更新最大面积。时间 O(n)、空间 O(1)。
如果这篇对你有帮助,点赞 / 收藏 / 关注。我会把双指针系列(移动零、盛水、接雨水、三数之和、最小覆盖子串等)做成合集,欢迎继续追更!
更多推荐


所有评论(0)