首页 简历|笔试面试
您现在的位置:百分网 > 职场 > 笔试面试 > LeetCode

16、最接近的三数之和

  • 25年9月4日 发布
  • 670.76KB 共5页
16、最接近的三数之和16、最接近的三数之和16、最接近的三数之和16、最接近的三数之和16、最接近的三数之和

16、最接近的三数之和

鲁迅说过,读书不觉已春深,一寸光阴一寸金。每天进步一点点,坚持下去,你

会发现,你的进步是惊人的。二哥的 LeetCode 刷题笔记,我要再刷一道三数之

和,举一反三。

题意

给你一个长度为 n 的整数数组 nums 和一个目标值 target。请你从 nums 中选出三个整

数,使它们的和与 target 最接近。

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

难度

中等

示例

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

输出:2

解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

输入:nums = [0,0,0], target = 1

输出:0

分析

既然是最接近的三数之和,那显然我们就可以采用 015 三数之和的题解思路,先排序,

然后固定一个数,再用双指针去找另外两个数。

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

016.%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%89%E6%95%B0%E4

%B9%8B%E5%92%8C-20240127114614.png

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

了。

import java.util.Arrays;

public class Solution {

public int threeSumClosest(int[] nums, int target) {

// 对数组进行排序

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) < Math.abs(target - closestSum)) {

// 更新最接近的和

closestSum = sum;

}

另外一个点是移动左指针还是右指针,当 sum 大于 target,说明 sum 太大了,需要减小

sum,那么就移动右指针,反之,如果 sum 小于 target,说明 sum 太小了,需要增大

sum,那么就移动左指针。

if (sum > target) {

right--; // 和大于目标值,移动右指针向左

} else if (sum < target) {

left++; // 和小于目标值,移动左指针向右

} else {

return sum; // 如果和等于目标值,直接返回当前和

}

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

了,需要增大 sum。

016.%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%89%E6%95%B0%E4

%B9%8B%E5%92%8C-20240127121258.png

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

016.%E6%9C%80%E6%8E%A5%E8%BF%91%E7%9A%84%E4%B8%89%E6%95%B0%E4

%B9%8B%E5%92%8C-20240127121419.png

总结

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

那刷题其实就是这样,学会举一反三,遇到不同的题型,尽量去找到和它相似的题型,能

不能按照之前的解题思路快速把这道题解出来,解出来后再想办法去优化。

这道题涉及到的 Java 基础知识,比如说 Arrays.sort、while 和 for 循环等等,之前也都提

到了,这里就不再赘述了。

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

开通会员 本次下载免费

所有资料全部免费下载! 推荐用户付费下载获取返佣积分! 积分可以兑换商品!
一键复制 下载文档 联系客服