持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情
题目:给定一个数组nums和一个目标值target,要求从nums中选出三个数,使得其之和与target最近。
解题思路
要解决本题,首先需要回顾之前三数之和的解题方法,在计算三数之和时采用的是三指针,在计算之前需要对数组进行排序,之后第一个指针固定,之后第二个指针的开始是第一个指针的下一个元素,而第三个指针的开始则是数组的最后一个元素,计算这三个指针对应的数字之和,如果和相等则这是一个正确解,如果大于则代表第三个指针的数字需要变小,否则代表左边指针数字需要变大。如此循环即可,具体细节不再讨论。
本题的解决方法是在三数之和的基础上进行改造的,三数之和的思路本质上是对所有可能的结果进行了无重复判断,本题可使用两个变量来分别记录最小距离和相对应的值,每次计算三数之和,如果和target的距离等于0则此时必然是最小距离,直接返回结果即可,否则根据其大小进行左右指针的移动,如果遇到距离小于当前距离,则更新距离和对应的值,可得代码如下:
public int threeSumClosest(int[] nums, int target) {
int distance = Integer.MAX_VALUE;
int resSum = 0;
Arrays.sort(nums);
for(int i=0;i<nums.length-1;i++){
if(i>0&&nums[i]==nums[i-1]) continue;
int L = i+1;
int R = nums.length-1;
while(L<R){
int temp = nums[i]+nums[L]+nums[R]-target;
if(Math.abs(temp)<distance){
distance = Math.abs(temp);
resSum = nums[i]+nums[L]+nums[R];
}
if(temp==0) return resSum;
if(temp>0){
R--;
while(L<R&&nums[R]==nums[R+1]) R--;
}else {
L++;
while(L<R&&nums[L]==nums[L-1]) L++;
}
}
}
return resSum;
}
在距离大于0和小于0时,理论上移动后应该判断数组中是否存在相同元素,如果存在则应该跳过,但使用这个逻辑则耗时7ms,去除则耗时5ms,最后看了是因为每组输入都只存在恰好一个解,因此去除会快一点。