力扣刷题#8:LeetCode11盛最多水的容器

这道题和我刚刷的三数之和用了同一种双指针模式,但思考方式又不太一样——这次不是求和,而是求最大面积。


题目

给定一个整数数组 height,每个元素代表一个垂直线的高度。找出两条线,使它们与 x 轴构成的容器能容纳最多的水。

输入: [1,8,6,2,5,4,8,3,7]
输出: 49
                   ↑     ↑
                 高度 8  高度 7, 距离 7
                 面积 = 7 × 7 = 49

从最宽的开始

三数之和的双指针是从两端往中间夹逼,这道题也是——但理由不同。

三数之和夹逼是因为要控制"和"的大小。这道题夹逼是因为:最宽的容器不一定最多水,但最宽的容器是一个合理的起点。

左右两个指针,一个在头一个在尾,这是你能得到的最宽容器。然后慢慢往中间收窄,在这个过程中找更高的柱子来弥补宽度损失。


核心决策:动哪一边?

面积 = min(height[l], height[r]) × (r - l)
         ↑                         ↑
       短板决定高度               宽度

每次算完当前面积,面临一个选择:移动左指针还是右指针?

关键洞察:永远移动较矮的那根柱子。

原因很直观:

假设 height[l] = 3, height[r] = 8

如果移动较高的(r):新的宽度变窄,高度 ≤ 8
  → 面积一定变小(宽度窄了,高度不可能超过 8)

如果移动较矮的(l):新的宽度变窄,但高度可能变大
  → 面积有可能变大(虽然窄了,但新柱子可能比 3 高)

移动较高的那根柱子,面积只会变小或持平,永远不会变大。
移动较矮的那根柱子,面积才有增加的可能性。

所以策略就是:哪边矮就移哪边,记录过程中的最大面积。


初版代码

int l = 0, r = height.size() - 1;
int sq = 0;
while (l < r) {
    sq = max(sq, min(height[l], height[r]) * (r - l));
    if (height[l] < height[r]) l++;
    else r--;
}
return sq;

4ms 通过。逻辑清晰,O(n) 复杂度,没有多余操作。


一个坑:宽度的计算

一个小细节但容易错——宽度的计算。

l=0, r=8 的时候,距离 = 8 - 0 = 8

不是 (r - l + 1),而是 (r - l)。因为两个柱子之间的"间隔数"比柱子数少 1。我第一次写的时候就栽在这了。


尝试优化:跳过不可能的柱子

4ms 通过了,但我想看看能不能更快。思路是:既然移动较矮的那根,那移动后如果遇到比原来还矮的柱子,面积一定更小,不如直接跳过。

if (height[l] < height[r]) {
    int minh = height[l];
    l++;
    sq = max(sq, min(height[l], height[r]) * (r - l));
    while (l < r && height[l] <= minh) l++;  // 跳过比刚才还矮的
}

理论上能减少比较次数,但实际踩了一个坑:跳过 while 执行完后没有重新算面积。

l=0, r=7, height[0]=6, height[7]=62
  → 左指针矮,跳过 while 执行了 5 次,l 直接跳到 6
  → 但 (l=6, r=7) 这个组合本应算一次面积 = min(99,62)×1 = 62
  → 被跳过了!最终输出 60 而不是 62

教训:跳过优化要在每个可能的组合上都算了面积之后再跳,否则可能漏掉最优解。

最后放弃了跳过优化——4ms 版已经是最优 O(n) 了,LeetCode 上 0ms 和 4ms 的差距通常是服务器波动,不值得花时间去追。


学到的东西

1. 这道题和三数之和都是左右夹逼

三数之和 盛最多水的容器
双指针方向 左右夹逼 左右夹逼
移动依据 和的大小决定 高度高低决定
移动方向 和小了左++,和大了右-- 哪边矮移哪边
记录什么 所有和为 0 的组合 过程中的最大面积

2. 跳过的代价

跳过优化看起来很美,但容易漏掉边界情况。对于 O(n) 的算法,跳过优化带来的常数提升往往微乎其微,但引入 bug 的风险却很实在。

与其优化常数,不如保证正确。 4ms 和 0ms 的区别不值得花时间去追。

3. 面积公式的直观理解

盛水量 = 短板高度 × 底部宽度

这个公式决定了"动较矮的那根"是最优策略——因为决定盛水量的不是较高的板,而是较矮的那块。你永远无法通过移动较高的板来提升容量上限。


写于 2026-06-06。双指针从"求和"到"求面积",判断条件换了但框架没变。

本文档由 AI 辅助生成,作者提供问题和思路,综合获得以上内容。

posted @ 2026-06-06 13:12  STA_running  阅读(5)  评论(0)    收藏  举报