题目描述
思路解析动画文字版
枚举所有线对,n² 个组合,n 一大就慢,而且大量组合明显没希望还白算。换个思路:从「最宽」的一对开始,每步只放弃一条注定没希望的线。
l、r 在最左最右,此时宽度最大。面积由矮的那条决定,所以移走矮的——因为留着它、宽度还只会变小,面积只会更差;只有移走它,才可能换到更高的线、把面积翻盘上去。这就是从暴力到双指针的关键转折。
准备 · 两端出发:左指针 l=0、右指针 r=5,从最宽的一对开始。best 先记 0,准备一路刷新。
第 1 次 · 算面积:当前面积 = min(1,7)×5 = 5,刷新 best=5。两条里左边的 1 是矮的,它就是瓶颈。
第 1 次 · 移矮的左:左边 1 比右边 7 矮,移走它(l 右移)。注意不是看面积大小,而是看谁矮就移谁。
第 2 次 · 算面积:l 来到 8:面积 = min(8,7)×4 = 28,刷新 best=28!这一步就是最终答案。被丢掉的 1(灰)以后不再看。
第 2 次 · 移矮的右:这回左边 8 高、右边 7 矮,所以移走右边(r 左移)。移矮边的判据每步重新看。
第 3 次 · 面积变小:负例分支:面积 = min(8,5)×3 = 15,比 best 还小,best 不更新。但右边 5 仍是矮的,必须照样移走它——不能因为面积变小就停或回头,宽度只会越来越小,留着矮边没有未来。
第 4 次 · 继续移矮:min(8,2)×2 = 4,更小,best 仍是 28。右边 2 矮,继续 r 左移。
第 5 次 · 最后一对:现在 l=1、r=2 紧挨着。面积 min(8,6)×1 = 6。右边 6 矮,移它:r 左移到 1,正好和 l 重合,循环停。全程 best 最大是 28,对应一开始那对 8 和 7。
面积受限于矮的一边,留着它宽度还在缩、注定更差;放弃矮的才有翻盘机会——这是对撞双指针里的贪心选择。
雷区实演 · 移错边丢掉最优解:反例真跑一遍:到了 l=1(8)、r=5(7),正确该移矮的右边、面积 28 已记下。可一旦记成「移高的」、把 8 移走,l 跳到 6,宽度还缩到 3,28 这对再也凑不出来。这就是为什么判据必须是「移矮」。
迁移阶梯:学会「两端收缩、每步移走拖后腿的一端」后,去同类的 三数之和:同样左右指针对撞,只是把「移矮」换成「按和的大小移」。再难一档是接雨水。也可以直接问小欧「11 和 15 的双指针判据有什么不同」。
边界三连:边界三连:极端输入先过一遍。
几个高频追问,记住答法。
参考代码
class Solution: def maxArea(self, height): l, r = 0, len(height) - 1 ans = 0 while l < r: ans = max(ans, (r - l) * min(height[l], height[r])) if height[l] < height[r]: l += 1 else: r -= 1 return ans复杂度
- 时间复杂度:O(n),l、r 一头一尾相向,每步必有一个指针前进一格、从不回头,加起来恰好走 n 步
- 空间复杂度:O(1),只用 l、r、ans 几个变量
可套用的代码模板
记住骨架:两端收缩、每步移走限制结果的那一端。本题里 measure = min(高)×宽、瓶颈 = 较矮边;换成三数之和就把 measure/瓶颈替成「按和判断」。和「有序找一对」的双指针同形,区别只在「移谁」的判据。
# 两端向中间收、每步放弃"拖后腿"的一边l, r, best = 0, n - 1, 初值while l < r: best = 更新(best, 用 l, r 算的值) if 谁是瓶颈 == 左: l += 1 else: r -= 1易错点
面试追问把动画讲成自己的话
追问为什么移动矮的那条指针?
追问双指针为什么不会漏掉答案?
追问两条线一样高时移哪个?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
接雨水
LeetCode 42 · 困难 · 沿着 双指针 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题