双指针对撞能解“盛最多水的容器”是因为面积由短板和宽度共同决定,移动长边时短板不变而宽度减小,面积必然不增;只移动较短边才可能提升短板高度,从而增大面积,该贪心策略经数学证明不会遗漏最优解。

双指针对撞为什么能解“盛最多水的容器”
因为面积由短板决定,移动长边只会让底变短、高不增,面积必然不增;只有移动当前较短的那条边,才可能找到更高的边来提升面积。这是贪心策略成立的关键前提,不是靠直觉猜的。
left 和 right 初始化与更新逻辑
初始化为数组首尾下标:int left = 0, right = height.size() - 1。每次计算当前面积后,必须移动较短边的指针:
- 若
height[left] ,执行 <code>left++ - 若
height[left] > height[right],执行right-- - 若相等,移动任意一个都行(比如
left++),因为此时两者一样短,移动任一都会让短板可能变化
不能同时移动两个,也不能固定移动某一边——否则会漏掉关键状态。
容易错的边界和性能细节
常见错误包括:循环条件写成 left (应为 <code>left ,相等时宽为 0,无意义);面积计算用错高度(必须取 <code>min(height[left], height[right]),不是平均或最大);整型溢出风险虽小但存在(int 存面积足够,但若题目改用超大坐标,需转 long long)。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
时间复杂度稳定 O(n),空间 O(1);比暴力 O(n²) 本质快在剪枝——每轮都排除掉一批不可能更优的状态。
一个最小可运行示例
输入 vector<int> height = {1,8,6,2,5,4,8,3,7}</int>,核心循环片段如下:
int max_area = 0;
int left = 0, right = height.size() - 1;
while (left < right) {
int h = min(height[left], height[right]);
int w = right - left;
max_area = max(max_area, h * w);
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
// 输出:49
注意:max_area 必须在移动指针前更新,否则会跳过当前状态;比较和移动顺序不能颠倒。
实际写的时候,最常卡在判断该移哪边和循环终止条件上。只要记住“动短板,停在 left < right”,其余都是自然推导。

















