LeetCode16:最接近的三数之和
给你一个长度为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
思路:
这个题目与LeetCode15:三数之和,不能说是一摸一样吧,只能说是丝毫不差。在三数之和中,是找到三数之和为零的那三个数字,而对于这道题,就是找到最接近target的那三个数,如果target=0,那么就是找到最可能是三数之和的那个数,这样一来就很相似了。
想要找到最终的结果,两者只有这样一个区别
解法:
因为和三数之和的题目不同,这道题有个前提,假定只有一个解,所以对于LeetCode15不能使用的暴力递归,在这里就可以使用,只是时间复杂度为O(n^3)
解法1:暴力递归
使用三个循环,找到三数之和与target差值最小的那一组就行,使用三个循环
不断的更新指针,三个循环遍历数组,得到min(min, a+b+c-target),然后保存差值最小的数组
解法2:排序+双指针
就和上述LeetCode15:三数之和,的解法一样了,将数组排完序之后,使用双指针得到三数之和与targt的差值最小值,得到结果。
①首先将给出的数组排序,按照从高到低,这样一来,对于一串数字,通过判断与target的大小,就可以采用前后同时遍历的方法
②使用两个指针,一个初始在列表开头,另一个初始在列表结尾,然后遍历中间数字相加
③如果a+b+c>target,那么将尾指针左移一个
④如果a+b+c<=target,将首指针右移一个
⑤每次遍历都更新min(min, abs(a+b+c-target))的值,如果abs(a+b+c-target)更小,则记录
⑥逐渐遍历移动指针,直到全部结束
全部流程
代码实现
public int threeSumClosest(int [] nums, int target){
// 排序数组
Arrays.sort(nums);
// 初始化结构
int res = nums[0] + nums[1] + nums[2];
// 开始遍历
for(int i = 0; i < nums.length; i++){
// 声明双指针
int L = i + 1, R = nums.length - 1;
// 只要左指针不大于右指针,就可以遍历
while(L < R){
// 三数之和
int sum = nums[L] + nums[i] + nums[R];
// 更新res
res = Math.min(res, Math.abs(sum - target))
// 判断三数之和与target大小,然后相应指针移动
if(sum > target) R--; else if(sum < target) L ++; else return res;
}
}
return res;
}
测试代码
public static void main(String[] args){
LeetCode16 lc = new LeetCode16();
Sysout.out.println(lc.threeSumClosest({-1,-5,2,4,0}, 1));
}
结果
0