最接近的三数之和 图解题解
找离目标最近的三数之和,排序之后对撞指针每次都知道该往哪走。
排好序后固定一张牌,另两张从剩余的两端往中间夹:三张合计比目标小就把左边换成更大的,比目标大就把右边换成更小的,每次都用「离目标最近」刷新记录。排序保证了每次能明确判断该往哪边移,不用把所有组合都试一遍。
这道题到底在问什么
- 输入
- nums=[-1,2,1,-4], target=1
- 输出
- 2 (-1 + 1 + 2,差 1)
最优解:一步一步想明白
- 3记住这条「固定一个数、双指针对撞、偏小左扩偏大右缩」,下面每一帧都在套它。
- 4固定下标 0(值 -8),双指针复位到 l=1、r=8。三数之和 -4。差 11 比之前更小,刷新最接近为 -4。
- 5上一组和偏小,左指针右移到 2(值 -4,更大)→ 三数之和 -2,往 target=7 靠。差 9 比之前更小,刷新最接近为 -2。
- 6上一组和偏小,左指针右移到 3(值 -2,更大)→ 三数之和 0,往 target=7 靠。差 7 比之前更小,刷新最接近为 0。
- 7上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 2,往 target=7 靠。差 5 比之前更小,刷新最接近为 2。
- 8上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 4,往 target=7 靠。差 3 比之前更小,刷新最接近为 4。
- 9上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 6,往 target=7 靠。差 1 比之前更小,刷新最接近为 6。
- 10上一组和偏小,左指针右移到 7(值 6,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 11固定下标 1(值 -6),双指针复位到 l=2、r=8。三数之和 0。差 7 没比当前最接近 6 更好,不更新。
- 12上一组和偏小,左指针右移到 3(值 -2,更大)→ 三数之和 2,往 target=7 靠。差 5 没比当前最接近 6 更好,不更新。
- 13上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
- 14上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 15上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 16上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
- 17固定下标 2(值 -4),双指针复位到 l=3、r=8。三数之和 4。差 3 没比当前最接近 6 更好,不更新。
- 18上一组和偏小,左指针右移到 4(值 0,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 19上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 20上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
- 21上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 22固定下标 3(值 -2),双指针复位到 l=4、r=8。三数之和 8。差 1 没比当前最接近 6 更好,不更新。
- 23上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 4,往 target=7 靠。差 3 没比当前最接近 6 更好,不更新。
- 24上一组和偏小,左指针右移到 5(值 2,更大)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 25上一组和偏小,左指针右移到 6(值 4,更大)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 26固定下标 4(值 0),双指针复位到 l=5、r=8。三数之和 12。差 5 没比当前最接近 6 更好,不更新。
- 27上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 8,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 28上一组和偏大,右指针左移到 6(值 4,更小)→ 三数之和 6,往 target=7 靠。差 1 没比当前最接近 6 更好,不更新。
- 29固定下标 5(值 2),双指针复位到 l=6、r=8。三数之和 16。差 9 没比当前最接近 6 更好,不更新。
- 30上一组和偏大,右指针左移到 7(值 6,更小)→ 三数之和 12,往 target=7 靠。差 5 没比当前最接近 6 更好,不更新。
- 31固定下标 6(值 4),双指针复位到 l=7、r=8。三数之和 20。差 13 没比当前最接近 6 更好,不更新。
- 32整趟扫完,最接近 target=7 的三数之和是 6(绿色高亮的三个数 -8 + 4 + 10)。外层 O(n) × 内层双指针 O(n) = O(n²)。
⚠️ 容易写错的地方
✗ 错:忘了先排序就上双指针
✓ 对:必须先 sort,双指针才有单调性
没排序时「偏小左扩」不成立
✗ 错:best 初值随便设 0
✓ 对:用前三个数之和初始化 best
设 0 会在全负/全正数组里误判最接近
✗ 错:比较时不取绝对值
✓ 对:要比 |sum-target|
比的是「差的大小」不是「差的正负」
完整代码(Python / C++ / Java)
Python
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 bestC++
int threeSumClosest(vector<int>& nums, int target){
sort(nums.begin(), nums.end());
int best = nums[0]+nums[1]+nums[2];
for(int i = 0; i < (int)nums.size()-2; i++){
int l = i+1, r = nums.size()-1;
while(l < r){
int s = nums[i]+nums[l]+nums[r];
if(abs(s-target) < abs(best-target)) best = s;
if(s < target) l++;
else if(s > target) r--;
else return s;
}
}
return best;
}Java
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums); // 先排序
int best = nums[0] + nums[1] + nums[2];
for (int i = 0; i < nums.length - 2; i++) {
int l = i + 1, r = nums.length - 1; // 双指针对撞
while (l < r) {
int s = nums[i] + nums[l] + nums[r];
if (Math.abs(s - target) < Math.abs(best - target))
best = s; // 记最接近的和
if (s < target) l++; // 偏小左扩
else if (s > target) r--; // 偏大右缩
else return s; // 正好命中
}
}
return best;
}复杂度
时间
O(n²)
排序 O(n log n),外层 n × 内层双指针 n
空间
O(1)
排序原地,只用几个指针/变量(不计排序栈)
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 最接近的三数之和 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
和三数之和(LC15)有什么区别?+
思路同源(排序 + 对撞双指针),但 LC15 找和恰好为 0 的所有不重复三元组、要去重;本题只求与 target 最接近的那一个和,不去重、不收集组合,维护一个 best 即可。
能不能提前剪枝加速?+
可以。固定 i 后,若 nums[i]+两个最小(l、l+1)已大于 best 能改善的上界、或 nums[i]+两个最大已确定方向,可跳过;但最坏仍是 O(n²)。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄把 最接近的三数之和 一步步讲透(全站已上线 905 份讲透,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
把这道题真正拿下
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。