盛最多水的容器 — AI 写了两版,第一版差点把面试官气走
读完本文你将了解:盛最多水容器的最优解法 | 从暴力到双指针的优化过程 | 面试中的表现要点
📋 题目
给定一个非负整数数组 height,每个元素代表坐标 (i, height[i]) 处的一条垂线。找出两条线,使它们与 x 轴共同构成的容器能够容纳最多的水。
| 项目 | 说明 |
|---|---|
| 输入 | height = [1,8,6,2,5,4,8,3,7] |
| 输出 | 49 |
| 约束 | n == height.length,2 ≤ n ≤ 10⁵,0 ≤ height[i] ≤ 10⁴ |
💡 先问一个问题
这题在 LeetCode 上被点了 23 万次赞,排进 Top 50 热门题。看起来简单——不就是"找两个柱子,算面积"嘛——但 90% 的人第一次写的解法,放到 10⁵ 长度的数组上会直接跑死。
猜猜 AI 第一次会怎么写?
🤖 第一版:AI 的朴素解法(暴力枚举)
AI 遇到"找两个东西"的问题,第一反应永远是嵌套循环:
defmax_area(height):""" 暴力法:穷举所有柱子组合 """n=len(height)max_water=0foriinrange(n):forjinrange(i+1,n):h=min(height[i],height[j])w=j-i area=h*w max_water=max(max_water,area)returnmax_water这版代码逻辑没问题。问题出在复杂度上:
时间复杂度:O(n²),空间复杂度:O(1)
放到一个 10⁵ 个元素的数组上,要执行约 50 亿次计算。不是"慢一点"的问题——是面试官直接喊停的水平。
不过暴力解给出了一个重要的观察:
面积 = min(左高度, 右高度) × (右下标 - 左下标)
这个公式告诉我们:面积受制于较短的那根柱子。
🧠 AI 的自我优化
提示 AI "优化一下"后,它往往会经历一个思考过程:
第 1 次提示:思路转变
“既然面积受限于较短的那根,那我试试从两边往中间走?”
defmax_area(height):""" 两指针:从两端向中间移动 """left,right=0,len(height)-1max_water=0whileleft<right:h=min(height[left],height[right])w=right-left max_water=max(max_water,h*w)ifheight[left]<height[right]:left+=1else:right-=1returnmax_water关键优化点:每次只移动较短的那端——因为面积受限于短板,移动长板不可能得到更大的面积。
时间复杂度:O(n),空间复杂度:O(1)
☕ Java 实现
publicintmaxArea(int[]height){intleft=0,right=height.length-1;intmaxWater=0;while(left<right){inth=Math.min(height[left],height[right]);intw=right-left;maxWater=Math.max(maxWater,h*w);if(height[left]<height[right]){left++;}else{right--;}}returnmaxWater;}第 2 次提示:证明它
AI 不会只满足于"看起来对",继续追问后它会给出一个直观证明:
假设 left=0, right=n-1,且 height[left] < height[right]:
- 如果移动 left(短板),新面积可能变大也可能变小
- 如果移动 right(长板),新面积一定 ≤ 当前面积(宽变小了,高受限于依然不变的 left 短板)
结论:移动短板不一定变大,但移动长板一定不会变大。所以策略就是——谁短移谁。
🔍 算法模式拆解
这道题属于Two Pointers(双指针)模式中的"相向双指针"子类。
适用场景:需要在一维数组中找两个元素,且满足某种约束条件时,尝试从两端向中间逼近。
核心特征:
- 数组有一定顺序(不一定已排序)
- 需要比较两个元素
- 可以证明移动某一边不会丢失最优解
同类题:
- 三数之和(Three Sum):固定一个指针,另外两个相向移动
- 接雨水(Trapping Rain Water):双指针加强版,需要记录左右最大值
🏗️ 真实产品场景
这道题在产品环境中的威力,远比你在 LeetCode 上感受到的大。
场景一:物流中的最优路线规划
你在做物流调度系统,要从 A 地运一批货到 B 地。每个站点有不同的装卸能力(就是 height),你需要选两个站点之间的最优运输路径。运力受限于较小站点的处理能力(短板效应),而距离越远路线成本越高——完全就是"盛水容器"的问题变形。
实际中可能同时有几千个站点参与调度,O(n) 和 O(n²) 的差距——前者毫秒级出结果,后者等几分钟都可能行。
场景二:数据库连接池的并发分配
数据库连接数受限于最小节点的并发能力(短板),每个连接池的实例位置就是"下标"。分配连接时,策略同样是"找两个节点,使有效吞吐量最大化"——这就是双指针的活。
✅ 面试官的点评
| 维度 | 合格线 | 加分项 |
|---|---|---|
| 理解题意 | 能说清面积公式 | 明确指出"短板效应" |
| 暴力解 | 写出 O(n²) | 主动分析复杂度瓶颈 |
| 双指针 | 写出双指针代码 | 证明为什么移动短板才可能变大 |
| 边界情况 | 处理 n=2 | 测试全升序/全降序数组 |
| 扩展 | 无 | 能引出"三数之和"同类题 |
常见踩坑:
- 只想着枚举,不提优化——面试官会问"还能更好吗?"
- 写双指针但说不清为什么是对的——能写对不代表理解透
- 忽略了大数溢出的可能性——如果 height 是 int 但面积用 int 存,可能溢出
📊 同类题推荐
- 三数之和(LeetCode 15):双指针 + 排序,固定一个再移动两个
- 接雨水(LeetCode 42):双指针进阶版,维护左右最大值的 trick
- 有效三角形的个数(LeetCode 611):也是固定一个,双指针扫描
来源说明:
- ✅ 已验证:LeetCode 官方题解 + AI 实测
- ✅ 代码已实测通过 LeetCode 测试用例
