一道题搞懂双指针:LeetCode 第11题「盛最多水的容器」竟然这么简单?

77 阅读3分钟

“看似暴力,实则优雅”——用两个指针,装下整个海洋。

大家好,我是你们的算法搭子 👋
今天我们要一起攻克 LeetCode 上一道经典中等题:第11题「盛最多水的容器」(Container With Most Water)。

别被“中等”吓到!这道题不仅思路巧妙,而且是双指针算法的教科书级案例。掌握它,你就能在面试中自信地说:“双指针?我熟!”


🧩 题目描述(LeetCode #11)

给你一个长度为 n 的整数数组 height,其中每个元素代表一条垂直线的高度。
现在请你找出两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

注意:你不能倾斜容器,且 n 至少为 2。

示例:
输入:height = [1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水的最大值为 49。

image.png


❌ 暴力解法:O(n²) 的陷阱

最直观的想法是什么?
枚举所有可能的左右边界,计算面积,取最大值。

for (let i = 0; i < n; i++) {
  for (let j = i + 1; j < n; j++) {
    area = (j - i) * Math.min(height[i], height[j]);
    max = Math.max(max, area);
  }
}

时间复杂度:O(n²)
空间复杂度:O(1)

但问题是——当 n = 10⁵ 时,循环次数高达 50亿次!直接超时 💥

所以,我们必须更聪明一点。


✨ 灵光一现:双指针的优雅策略

🤔 核心思想

  • 初始时,左指针在最左(0),右指针在最右(n-1) ,此时宽度最大。
  • 容器的面积 = 宽度 × min(左高, 右高)
  • 要想面积更大,必须尝试更高的边,因为宽度只会越来越小!

🔑 关键洞察:

移动较矮的那一边,才有可能找到更大的面积!

为什么?
假设 height[left] < height[right],那么当前面积受限于 left 的高度。
即使你移动 right,宽度变小,高度也不会超过 height[left],面积只会更小。
所以,唯一有希望提升面积的方式,是移动 left,寻找更高的左边界!

同理,如果右边更矮,就移动右边。

这就是贪心 + 双指针的完美结合!


💡 正确代码(JavaScript)

/**
 * @param {number[]} height
 * @return {number}
 */
var maxArea = function(height) {
    let ans = 0;
    
    let left = 0;
    let right = height.length - 1;
    while(left < right) {
        let area = (right - left)*(Math.min(height[left],height[right]));
        ans = Math.max(area,ans);
        if(height[left]>height[right]){
            right--;
        }else{
            left++;
        }
    }
    return ans;
};

✅ 时间复杂度:O(n)
✅ 空间复杂度:O(1)

image.png


🎯 为什么这个策略不会漏掉最优解?

这是很多人卡住的地方: “万一最优解在中间,而我跳过了怎么办?”

我们来反证一下:

假设真实最优解是 (i, j),而我们的双指针在某一步跳过了 ij

但注意:只有当一边比另一边矮时,我们才会移动它
在到达 (i, j) 之前,左右指针一定分别从两端向内收缩。
只要 ij 还没相遇,它们就一定会被遍历到 —— 因为我们只在“不可能更优”的情况下才移动指针。

换句话说:每一步都保留了“可能成为最优解”的那一侧

这不是玄学,是数学上的贪心正确性保证!


🧠 延伸思考

  • 如果允许倾斜容器?(那就不是这道题了 😂)
  • 如果数组中有负数?(题目规定高度 ≥ 0)
  • 能不能用单调栈?(可以,但没必要,双指针更优)

✅ 总结:双指针的三大特征

当你遇到以下情况,可以考虑双指针:

  1. 数组或字符串问题
  2. 需要比较两端元素(如回文、对撞)
  3. 存在“移动某一边能排除无效解”的贪心策略

而这道题,完美契合!


🌟 最后送你一句口诀:

“水桶短板定容量,双指贪心移短边;宽减高升寻最大,一次遍历稳如山。”


如果你觉得这篇文章帮你打通了双指针的任督二脉,欢迎点赞 ❤️、收藏 ⭐、转发 🔄
也欢迎在评论区留下你的解法或疑问,我们一起刷穿 LeetCode!