题目描述
思路解析动画文字版
记住这条「固定一个数、双指针对撞、偏小左扩偏大右缩」,下面每一帧都在套它。
固定下标 0(值 -8),双指针复位到 l=1、r=8。三数之和 -4。差 11 比之前更小,刷新最接近为 -4。
上一组和偏小,左指针右移到 2(值 -4,更大)→ 三数之和 -2,往 target=7 靠。差 9 比之前更小,刷新最接近为 -2。
上一组和偏小,左指针右移到 3(值 -2,更大)→ 三数之和 0,往 target=7 靠。差 7 比之前更小,刷新最接近为 0。
上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 2,往 target=7 靠。差 5 比之前更小,刷新最接近为 2。
上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 4,往 target=7 靠。差 3 比之前更小,刷新最接近为 4。
上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 6,往 target=7 靠。差 1 比之前更小,刷新最接近为 6。
上一组和偏小,左指针右移到 7(值 6,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
固定下标 1(值 -6),双指针复位到 l=2、r=8。三数之和 0。差 7 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 3(值 -2,更大)→ 三数之和 2,往 target=7 靠。差 5 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
固定下标 2(值 -4),双指针复位到 l=3、r=8。三数之和 4。差 3 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
固定下标 3(值 -2),双指针复位到 l=4、r=8。三数之和 8。差 1 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
固定下标 4(值 0),双指针复位到 l=5、r=8。三数之和 12。差 5 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 6(值 4,更小)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
固定下标 5(值 2),双指针复位到 l=6、r=8。三数之和 16。差 9 没比当前最接近 6 更好,不更新。
上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 12,往 target=7 靠。差 5 没比当前最接近 6 更好,不更新。
固定下标 6(值 4),双指针复位到 l=7、r=8。三数之和 20。差 13 没比当前最接近 6 更好,不更新。
整趟扫完,最接近 target=7 的三数之和是 6(绿色高亮的三个数 -8 + 4 + 10)。外层 O(n) × 内层双指针 O(n) = O(n²)。
边界先想清:哪怕离 target 很远,也要返回能凑到的最接近的那个和。
两个高频追问,串起「3Sum 家族」的共同套路。
参考代码
def threeSumClosest(nums, target): nums.sort() # 先排序 best = nums[0] + nums[1] + nums[2] for i in range(len(nums) - 2): l, r = i + 1, len(nums) - 1 # 双指针对撞 while l < r: s = nums[i] + nums[l] + nums[r] if abs(s - target) < abs(best - target): best = s # 记最接近 if s < target: l += 1 # 偏小左扩 elif s > target: r -= 1 # 偏大右缩 else: return s # 正好命中 return best复杂度
- 时间:O(n²),排序 O(n log n),外层 n × 内层双指针 n
- 空间:O(1),排序原地,只用几个指针/变量(不计排序栈)
易错点
面试追问把动画讲成自己的话
追问和三数之和(LC15)有什么区别?
追问能不能提前剪枝加速?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
四数之和
LeetCode 18 · 中等 · 沿着 双指针 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题