5444 字
约 18 分钟
2
016.最接近的三数之和
无标签

016.最接近的三数之和

作者:沉默王二 发布时间:2024-01-27T12:24:22.654+0800


鲁迅说过,读书不觉已春深,一寸光阴一寸金。每天进步一点点,坚持下去,你会发现,你的进步是惊人的。二哥的 LeetCode 刷题笔记,我要再刷一道三数之和,举一反三。

技术派阅读地址:https://paicoding.com/column/7/16

  • 语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu

  • 这道题可以说完全重写了,给出1道大家完全都能掌握的题解(双指针)。

  • 增加代码注释,这样大家更容易看懂并掌握题解;

  • 增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;

  • 增加手绘图,这样大家更容易理解解题思路;

  • 增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;

  • 增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;

  • 图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。

  • 另外,这一版本会作为 PDF 的终稿随后在星球进行发布。

题意

给你一个长度为 n 的整数数组 nums 和一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。假定每组输入只存在恰好一个解。

难度

中等

示例

输入:nums = [-1,2,1,-4], target = 1

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。 输入:nums = [0,0,0], target = 1输出:0

分析

既然是最接近的三数之和,那显然我们就可以采用**015三数之和 **的题解思路,先排序,然后固定一个数,再用双指针去找另外两个数。

对三数之和的题解思路不熟悉的球友,可以回头再温故一下。

三数之和的时候和为 0,这里的和为最接近 target 的一个数,那其实解法就真的差不多了。

class Solution {
    // 对数组进行排序        Arrays.sort(nums);        // 数组长度        int n = nums.length;        // 初始化最接近的和为前三个元素的和        int closestSum = nums[0] + nums[1] + nums[2];
    // 遍历数组,除了最后两个元素(因为我们需要三个数)        for (int i = 0; i < n - 2; i++) {            // 双指针初始化,left 指向当前元素之后的元素,right 指向数组最后一个元素            int left = i + 1, right = n - 1;            while (left < right) {                // 计算当前三个数的和                int sum = nums[i] + nums[left] + nums[right];                // 如果当前和与目标值的差的绝对值小于最接近和与目标值的差的绝对值                if (Math.abs(target - sum) < Math.abs(target - closestSum)) {                    // 更新最接近的和                    closestSum = sum;                }                // 根据和与目标值的比较,移动指针                if (sum > target) {                    right--; // 和大于目标值,移动右指针向左                } else if (sum < target) {                    left++; // 和小于目标值,移动左指针向右                } else {                    return sum; // 如果和等于目标值,直接返回当前和                }            }        }        // 返回找到的最接近的和        return closestSum;    }}

我们来简单分析下:

①、排序:首先对数组进行排序。双指针的前提就是数组要有序,这样才方便移动指针。

②、初始化最接近 target 的和:假设数组中前三个数的和就是最进阶 target 的值。

③、遍历数组:遍历数组,固定一个数 nums[i]。

  • 双指针查找:在 nums[i] 后面的数组部分设置双指针,一个是 i 的下一位 i + 1,另一个是数组的末尾 n - 1。
  • 移动这两个指针,寻找和最接近 target 的三数组合。
  • 更新最接近的和:如果找到更接近 target 的和,就更新这个最接近的和。比如说,初始的和为 10,target 为 2,那如果我们找到了一个和为 5 的三数组合,那这个和就比 10 更接近 2,所以我们就更新这个最接近的和为 5。

④、终止条件:如果某次三数之和等于 target,直接返回 target,因为不能更接近了。

这里需要注意的两个点,一个是如何判断最接近的和,我们用了 Math.abs () 方法,这个方法是取绝对值的意思,比如说 Math.abs (-1) 的结果就是 1,Math.abs (1) 的结果还是 1。

当一个数与目标数 target 的差越小,那么这个数也就越接近 target。相信大家都能理解,5-3=2 < 10-3=7,那么 5 就比 10 更接近 3。

if (Math.abs(target - sum) 	closestSum = sum;}

另外一个点是移动左指针还是右指针,当 sum 大于 target,说明 sum 太大了,需要减小 sum,那么就移动右指针,反之,如果 sum 小于 target,说明 sum 太小了,需要增大 sum,那么就移动左指针。

if (sum > target) {

} else if (sum < target) {	left++; // 和小于目标值,移动左指针向右} else {	return sum; // 如果和等于目标值,直接返回当前和}

当输入是 nums = [-1,2,1,-4], target = 1 的时候,就需要移动左指针,因为 sum 太小了,需要增大 sum。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_10.png)

好,来看一下题解效率,还不错。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_11.png)

### **总结**

本题和**[015.三数之和](https://paicoding.com/column/7/15)**非常相似,题解的内核也一模一样,只有细微的差别。

那刷题其实就是这样,学会举一反三,遇到不同的题型,尽量去找到和它相似的题型,能不能按照之前的解题思路快速把这道题解出来,解出来后再想办法去优化。

这道题涉及到的 Java 基础知识,比如说 [Arrays.sort](http://Arrays.sort)、while 和 for 循环等等,之前也都提到了,这里就不再赘述了。

力扣链接:**[https://leetcode.cn/problems/3sum-closest/](https://leetcode.cn/problems/3sum-closest/)**

### **一步一个脚印**

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

该题解目前只针对**[二哥编程星球](https://javabetter.cn/zhishixingqiu/)**的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_12.png)

(优惠券仅 300 张,数量有限)

一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。

        
        
鲁迅说过,读书不觉已春深,一寸光阴一寸金。每天进步一点点,坚持下去,你会发现,你的进步是惊人的。二哥的 LeetCode 刷题笔记,我要再刷一道三数之和,举一反三。

技术派阅读地址:[https://paicoding.com/column/7/16](https://paicoding.com/column/7/16)

- 语雀专栏地址+密码可通过星球置顶帖查看:[https://t.zsxq.com/15rEo9Pdu](https://t.zsxq.com/15rEo9Pdu)
- 这道题可以说完全重写了,给出1道大家完全都能掌握的题解(双指针)。

- 增加代码注释,这样大家更容易看懂并掌握题解;
- 增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;
- 增加手绘图,这样大家更容易理解解题思路;
- 增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;
- 增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;
- 图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。
- 另外,这一版本会作为 PDF 的终稿随后在星球进行发布。

### **题意**

给你一个长度为 n 的整数数组 nums 和一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。假定每组输入只存在恰好一个解。

### **难度**

中等

### **示例**

输入:nums = [-1,2,1,-4], target = 1

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
输入:nums = [0,0,0], target = 1输出:0

### **分析**

既然是最接近的三数之和,那显然我们就可以采用**[015三数之和](https://paicoding.com/column/7/15)**的题解思路,先排序,然后固定一个数,再用双指针去找另外两个数。

对三数之和的题解思路不熟悉的球友,可以回头再温故一下。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_09.png)

三数之和的时候和为 0,这里的和为最接近 target 的一个数,那其实解法就真的差不多了。

class Solution {

        // 对数组进行排序        Arrays.sort(nums);        // 数组长度        int n = nums.length;        // 初始化最接近的和为前三个元素的和        int closestSum = nums[0] + nums[1] + nums[2];
        // 遍历数组,除了最后两个元素(因为我们需要三个数)        for (int i = 0; i < n - 2; i++) {            // 双指针初始化,left 指向当前元素之后的元素,right 指向数组最后一个元素            int left = i + 1, right = n - 1;            while (left < right) {                // 计算当前三个数的和                int sum = nums[i] + nums[left] + nums[right];                // 如果当前和与目标值的差的绝对值小于最接近和与目标值的差的绝对值                if (Math.abs(target - sum) < Math.abs(target - closestSum)) {                    // 更新最接近的和                    closestSum = sum;                }                // 根据和与目标值的比较,移动指针                if (sum > target) {                    right--; // 和大于目标值,移动右指针向左                } else if (sum < target) {                    left++; // 和小于目标值,移动左指针向右                } else {                    return sum; // 如果和等于目标值,直接返回当前和                }            }        }        // 返回找到的最接近的和        return closestSum;    }}

我们来简单分析下:

①、排序:首先对数组进行排序。双指针的前提就是数组要有序,这样才方便移动指针。

②、初始化最接近 target 的和:假设数组中前三个数的和就是最进阶 target 的值。

③、遍历数组:遍历数组,固定一个数 nums[i]。

- 双指针查找:在 nums[i] 后面的数组部分设置双指针,一个是 i 的下一位 i + 1,另一个是数组的末尾 n - 1。
- 移动这两个指针,寻找和最接近 target 的三数组合。
- 更新最接近的和:如果找到更接近 target 的和,就更新这个最接近的和。比如说,初始的和为 10,target 为 2,那如果我们找到了一个和为 5 的三数组合,那这个和就比 10 更接近 2,所以我们就更新这个最接近的和为 5。

④、终止条件:如果某次三数之和等于 target,直接返回 target,因为不能更接近了。

这里需要注意的两个点,一个是如何判断最接近的和,我们用了 [Math.abs](http://Math.abs)() 方法,这个方法是取绝对值的意思,比如说 [Math.abs](http://Math.abs)(-1) 的结果就是 1,[Math.abs](http://Math.abs)(1) 的结果还是 1。

当一个数与目标数 target 的差越小,那么这个数也就越接近 target。相信大家都能理解,5-3=2 < 10-3=7,那么 5 就比 10 更接近 3。

if (Math.abs(target - sum) closestSum = sum;}

另外一个点是移动左指针还是右指针,当 sum 大于 target,说明 sum 太大了,需要减小 sum,那么就移动右指针,反之,如果 sum 小于 target,说明 sum 太小了,需要增大 sum,那么就移动左指针。

if (sum > target) {

} else if (sum < target) { left++; // 和小于目标值,移动左指针向右} else { return sum; // 如果和等于目标值,直接返回当前和}

当输入是 nums = [-1,2,1,-4], target = 1 的时候,就需要移动左指针,因为 sum 太小了,需要增大 sum。

好,来看一下题解效率,还不错。

总结

本题和**015.三数之和 **非常相似,题解的内核也一模一样,只有细微的差别。

那刷题其实就是这样,学会举一反三,遇到不同的题型,尽量去找到和它相似的题型,能不能按照之前的解题思路快速把这道题解出来,解出来后再想办法去优化。

这道题涉及到的 Java 基础知识,比如说 Arrays.sort 、while 和 for 循环等等,之前也都提到了,这里就不再赘述了。

力扣链接:https://leetcode.cn/problems/3sum-closest/

一步一个脚印

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

该题解目前只针对**二哥编程星球 **的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。

(优惠券仅 300 张,数量有限)

一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。

鲁迅说过,读书不觉已春深,一寸光阴一寸金。每天进步一点点,坚持下去,你会发现,你的进步是惊人的。二哥的 LeetCode 刷题笔记,我要再刷一道三数之和,举一反三。

技术派阅读地址:https://paicoding.com/column/7/16

  • 语雀专栏地址+密码可通过星球置顶帖查看:https://t.zsxq.com/15rEo9Pdu

  • 这道题可以说完全重写了,给出1道大家完全都能掌握的题解(双指针)。

  • 增加代码注释,这样大家更容易看懂并掌握题解;

  • 增加参考资料,这样大家可以从零基础直接开刷,减轻新手刷题的阻力;

  • 增加手绘图,这样大家更容易理解解题思路;

  • 增加 ACM 输入输出,这样大家可以在 Intellij IDEA 中进行调试;

  • 增加题解模拟,这样大家可以根据题解模拟整个题解过程,看完会有一种“哦哦”恍然大悟的感觉;

  • 图片上传至 OSS 并配合 CDN,提升大家在技术派网站中的阅读体感。

  • 另外,这一版本会作为 PDF 的终稿随后在星球进行发布。

题意

给你一个长度为 n 的整数数组 nums 和一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。假定每组输入只存在恰好一个解。

难度

中等

示例

输入:nums = [-1,2,1,-4], target = 1

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。 输入:nums = [0,0,0], target = 1输出:0

分析

既然是最接近的三数之和,那显然我们就可以采用**015三数之和 **的题解思路,先排序,然后固定一个数,再用双指针去找另外两个数。

对三数之和的题解思路不熟悉的球友,可以回头再温故一下。

三数之和的时候和为 0,这里的和为最接近 target 的一个数,那其实解法就真的差不多了。

class Solution {
    // 对数组进行排序        Arrays.sort(nums);        // 数组长度        int n = nums.length;        // 初始化最接近的和为前三个元素的和        int closestSum = nums[0] + nums[1] + nums[2];
    // 遍历数组,除了最后两个元素(因为我们需要三个数)        for (int i = 0; i < n - 2; i++) {            // 双指针初始化,left 指向当前元素之后的元素,right 指向数组最后一个元素            int left = i + 1, right = n - 1;            while (left < right) {                // 计算当前三个数的和                int sum = nums[i] + nums[left] + nums[right];                // 如果当前和与目标值的差的绝对值小于最接近和与目标值的差的绝对值                if (Math.abs(target - sum) < Math.abs(target - closestSum)) {                    // 更新最接近的和                    closestSum = sum;                }                // 根据和与目标值的比较,移动指针                if (sum > target) {                    right--; // 和大于目标值,移动右指针向左                } else if (sum < target) {                    left++; // 和小于目标值,移动左指针向右                } else {                    return sum; // 如果和等于目标值,直接返回当前和                }            }        }        // 返回找到的最接近的和        return closestSum;    }}

我们来简单分析下:

①、排序:首先对数组进行排序。双指针的前提就是数组要有序,这样才方便移动指针。

②、初始化最接近 target 的和:假设数组中前三个数的和就是最进阶 target 的值。

③、遍历数组:遍历数组,固定一个数 nums[i]。

  • 双指针查找:在 nums[i] 后面的数组部分设置双指针,一个是 i 的下一位 i + 1,另一个是数组的末尾 n - 1。
  • 移动这两个指针,寻找和最接近 target 的三数组合。
  • 更新最接近的和:如果找到更接近 target 的和,就更新这个最接近的和。比如说,初始的和为 10,target 为 2,那如果我们找到了一个和为 5 的三数组合,那这个和就比 10 更接近 2,所以我们就更新这个最接近的和为 5。

④、终止条件:如果某次三数之和等于 target,直接返回 target,因为不能更接近了。

这里需要注意的两个点,一个是如何判断最接近的和,我们用了 Math.abs () 方法,这个方法是取绝对值的意思,比如说 Math.abs (-1) 的结果就是 1,Math.abs (1) 的结果还是 1。

当一个数与目标数 target 的差越小,那么这个数也就越接近 target。相信大家都能理解,5-3=2 < 10-3=7,那么 5 就比 10 更接近 3。

if (Math.abs(target - sum) 	closestSum = sum;}

另外一个点是移动左指针还是右指针,当 sum 大于 target,说明 sum 太大了,需要减小 sum,那么就移动右指针,反之,如果 sum 小于 target,说明 sum 太小了,需要增大 sum,那么就移动左指针。

if (sum > target) {

} else if (sum < target) {	left++; // 和小于目标值,移动左指针向右} else {	return sum; // 如果和等于目标值,直接返回当前和}

当输入是 nums = [-1,2,1,-4], target = 1 的时候,就需要移动左指针,因为 sum 太小了,需要增大 sum。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_10.png)

好,来看一下题解效率,还不错。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_11.png)

### **总结**

本题和**[015.三数之和](https://paicoding.com/column/7/15)**非常相似,题解的内核也一模一样,只有细微的差别。

那刷题其实就是这样,学会举一反三,遇到不同的题型,尽量去找到和它相似的题型,能不能按照之前的解题思路快速把这道题解出来,解出来后再想办法去优化。

这道题涉及到的 Java 基础知识,比如说 [Arrays.sort](http://Arrays.sort)、while 和 for 循环等等,之前也都提到了,这里就不再赘述了。

力扣链接:**[https://leetcode.cn/problems/3sum-closest/](https://leetcode.cn/problems/3sum-closest/)**

### **一步一个脚印**

不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。

该题解目前只针对**[二哥编程星球](https://javabetter.cn/zhishixingqiu/)**的球友开放,如果你也想一起打卡学习算法的话,扫下面的优惠券加入我们吧,星球目前 4300+ 人,定价 149 元,从当初的 99 元一路涨上来的,所以早就是优势,别再犹豫了。

![图片](https://clxhuhhr.top/uploads/weblog/erge/erge_lc_image_12.png)

(优惠券仅 300 张,数量有限)

一个人可以走得很快,但一群人才能走得更远。如果想去面中大厂的话,LeetCode 几乎是必刷的,二哥的 LeetCode 题解通俗易懂、图文并茂,理解给你举一反三的解题能力,冲鸭。

        
                
                
                知识星球
                
        
        
            
            扫码加入星球
            查看更多优质内容
        
        https://wx.zsxq.com/mweb/views/joingroup/join_group.html?group_id=15522885221412
016.最接近的三数之和
http://www.clxhxhhr.top/posts/2441/
作者
clxstart
发布于
2026-09-19
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。