【Hot100-Java中等】LeetCode 11. 盛最多水的容器:双指针法的直观理解与数学证明

在 LeetCode 的 Hot 100 题单中,第 11 题"盛最多水的容器"是一道极具代表性的题目。它不仅考察编程技巧,更考察通过数学逻辑优化算法的能力。

这道题的暴力解法很容易想到,但要达到 的最优复杂度,需要利用双指针技巧。今天我们就来深入剖析这道题。

1. 题目核心分析

题目描述 :给定一个数组 height,数组中的每个元素代表一条垂直线的长度。找出两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

核心公式:

我们面临的是一个权衡问题:

  • 想要面积大,宽度(距离)要大。

  • 想要面积大,高度(短板)也要高。

    但因为木桶效应,容器的高度取决于两边较短的那条线。


2. 为什么暴力法不可行?

最直观的想法是两层 for 循环,枚举所有可能的组合 (i, j),计算面积并取最大值。

  • 时间复杂度 :。

  • 数据范围 :题目提示 。

  • 结果 : 的平方是 ,这远远超过了计算机 1 秒钟的处理能力(约 次运算),会导致 超时 (TLE)。

因此,我们需要寻找一种线性时间 O(N) 的解法。


3. 核心解法:双指针 (Double Pointer)

算法流程

我们采用"缩减搜索空间"的策略。

  1. 初始状态 :定义两个指针,left 指向数组开头,right 指向数组结尾。此时宽度最大。

  2. 计算面积 :计算当前 left 和 right 围成的面积,更新最大值 maxArea。

  3. 移动策略(关键):

    • 如果 height[left] < height[right]:移动左指针 (left++)。

    • 如果 height[left] >= height[right]:移动右指针 (right--)。

    • 口诀 :谁短动谁。

  4. 终止条件 :当 left 和 right 相遇时停止。

为什么是"谁短动谁"?(直观理解)

假设现在 left 处的线比 right 处的线短。

  • 如果不移动 left(短板),而是移动 right(长板):

    • 宽度:一定变小。

    • 高度 :受限于 left(短板)。无论 right 移过来的新线有多高,整个容器的高度绝不可能超过 left 的高度。如果新线比 left 还矮,高度甚至会更低。

    • 结论 :宽度变小,高度不变或变小 面积一定变小。

这意味着,只要 left 是短板,这一轮以 left 为边界的所有情况(left 和任意 right 的组合)中,最开始算的那次(最远距离)就是最大的。left 已经没有利用价值了,所以我们丢弃 left,尝试找一根更高的线。


4. 严谨的数学证明

如果你觉得直观理解不够严谨,我们来看一下数学推导。

假设当前左右指针分别为 和 ,且 (左边是短板)。

当前的距离为 。

当前面积 。

证明:为什么要移动 ?

我们要证明的是:在保留 的情况下,无论 R 向左移动到任何位置 (),得到的面积 一定小于等于 。

  1. 新的宽度 ,显然 。

  2. 新的高度 。

    • 因为高度由短板决定,所以 恒成立。
  3. 新面积 。

    • 因为 且 。

    • 所以 恒成立。

结论 :只要确定了 是短板,那么 与 右边任意一条线的组合,最大面积只能是当前算出来的这个。因此,我们可以安全地排除 ,去探索新的可能性。


5. 代码实现 (Java)

Java

复制代码
class Solution {
    public int maxArea(int[] height) {
        // 定义双指针,分别指向头尾
        int l = 0, r = height.length - 1;
        int ans = 0;
        
        while (l < r) {
            // 1. 计算当前面积
            // 高度由短板决定
            int currentHeight = Math.min(height[l], height[r]);
            // 宽度是索引差
            int currentWidth = r - l;
            int area = currentHeight * currentWidth;
            
            // 2. 更新最大面积
            ans = Math.max(ans, area);
            
            // 3. 移动策略:谁短动谁
            // 移动短板是为了试图找到更高的板子,从而可能抵消宽度的减小
            if (height[l] <= height[r]) {
                l++;
            } else {
                r--;
            }
        }
        return ans;
    }
}

6. 复杂度分析

  • 时间复杂度 :

    • 双指针 l 和 r 总共遍历整个数组一次。每个元素最多被访问一次。
  • 空间复杂度 :

    • 只需要存储 l, r, ans 等几个变量,不需要额外的数组空间。

7. 总结

LeetCode 11 题是贪心思想 与双指针结合的典范。

解决此题的关键在于打破"遍历所有组合"的思维定势,转而思考:什么情况下我们能确定一条边已经发挥了最大潜力,可以被安全地"丢弃"?

  • Wood Bucket Theory(木桶理论):短板决定容量。

  • 消去法:移动短板那一侧的指针,相当于排除了该短板与其他所有远端边组合的可能性,因为它们一定比当前面积小。

相关推荐
UIU1146 小时前
P1233 [ICPC 2001 Taejon R] 木棍加工
数据结构·c++·算法·动态规划
论文复现现场7 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
ZhengEnCi7 小时前
用 AI 写代码为什么拼到最后还是拼人:算力瓶颈与领域专家提示词的本质差异
算法·架构
秋天的怀念_David8 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
碧海银沙音频科技研究院9 小时前
在PC电脑上用Whisper→Marian算法实现离线语音翻译功能
算法·whisper
niyongsheng9 小时前
3D 装箱算法工程化:数据结构、放置启发式与支撑规则
数据结构·算法·rust
j7~12 小时前
【穷举、深搜与回溯算法】一棵决策树讲透全排列与子集
数据结构·c++·算法·leetcode·回溯·递归
傅科摆 _ py13 小时前
DP,贪心,堆和栈,二分力扣复习
开发语言·python·算法
Shaoshing13 小时前
LeetCode100 42.接雨水
java·算法·leetcode
域限奇点访客13 小时前
用AI生成问卷的网站怎么选?看题目录入结构、题型映射和生成后的校验
算法