在 LeetCode 的 Hot 100 题单中,第 11 题"盛最多水的容器"是一道极具代表性的题目。它不仅考察编程技巧,更考察通过数学逻辑优化算法的能力。
这道题的暴力解法很容易想到,但要达到 的最优复杂度,需要利用双指针技巧。今天我们就来深入剖析这道题。
1. 题目核心分析
题目描述 :给定一个数组 height,数组中的每个元素代表一条垂直线的长度。找出两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
核心公式:
我们面临的是一个权衡问题:
-
想要面积大,宽度(距离)要大。
-
想要面积大,高度(短板)也要高。
但因为木桶效应,容器的高度取决于两边较短的那条线。
2. 为什么暴力法不可行?
最直观的想法是两层 for 循环,枚举所有可能的组合 (i, j),计算面积并取最大值。
-
时间复杂度 :
。
-
数据范围 :题目提示
。
-
结果 :
的平方是
,这远远超过了计算机 1 秒钟的处理能力(约
次运算),会导致 超时 (TLE)。
因此,我们需要寻找一种线性时间 O(N) 的解法。
3. 核心解法:双指针 (Double Pointer)
算法流程
我们采用"缩减搜索空间"的策略。
-
初始状态 :定义两个指针,
left指向数组开头,right指向数组结尾。此时宽度最大。 -
计算面积 :计算当前
left和right围成的面积,更新最大值maxArea。 -
移动策略(关键):
-
如果
height[left] < height[right]:移动左指针 (left++)。 -
如果
height[left] >= height[right]:移动右指针 (right--)。 -
口诀 :谁短动谁。
-
-
终止条件 :当
left和right相遇时停止。
为什么是"谁短动谁"?(直观理解)
假设现在 left 处的线比 right 处的线短。
-
如果不移动
left(短板),而是移动right(长板):-
宽度:一定变小。
-
高度 :受限于
left(短板)。无论right移过来的新线有多高,整个容器的高度绝不可能超过left的高度。如果新线比left还矮,高度甚至会更低。 -
结论 :宽度变小,高度不变或变小
面积一定变小。
-
这意味着,只要 left 是短板,这一轮以 left 为边界的所有情况(left 和任意 right 的组合)中,最开始算的那次(最远距离)就是最大的。left 已经没有利用价值了,所以我们丢弃 left,尝试找一根更高的线。
4. 严谨的数学证明
如果你觉得直观理解不够严谨,我们来看一下数学推导。
假设当前左右指针分别为 和
,且
(左边是短板)。
当前的距离为 。
当前面积 。
证明:为什么要移动 ?
我们要证明的是:在保留 的情况下,无论 R 向左移动到任何位置
(
),得到的面积
一定小于等于
。
-
新的宽度
,显然
。
-
新的高度
。
- 因为高度由短板决定,所以
恒成立。
- 因为高度由短板决定,所以
-
新面积
。
-
因为
且
。
-
所以
恒成立。
-
结论 :只要确定了 是短板,那么
与
右边任意一条线的组合,最大面积只能是当前算出来的这个。因此,我们可以安全地排除
,去探索新的可能性。
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(木桶理论):短板决定容量。
-
消去法:移动短板那一侧的指针,相当于排除了该短板与其他所有远端边组合的可能性,因为它们一定比当前面积小。