16. 最接近的三数之和
- 1)题目
- 2)思路
- 3)代码
- 4)结果
1)题目
给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1
输出:0
提示:
- 3 <= nums.length <= 1000
- -1000 <= nums[i] <= 1000
- -104 <= target <= 104
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum-closest
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2)思路
思路跟上一题差不多,
先进行数组排序,nums = [-1,2,1,-4], target = 1
-4, -1, 1, 2
i j k
然后判断和是否与target相等,相等直接返回该值;
不相等,和比target小,j右移一位,和比target大,k左移一位,再进行判断;
j==k时,i右移一位,j,k重新赋值进行判断;
过程要去重,减少重复判断。
一开始没想到结果要初始化为哪个值比较好,就用String进行赋值。
后来想到可以用前三个数的和作为初始值,反正后面都要判断。
可以看到执行用时从137ms降到了18ms,快了不少。
虽然比不上那些大佬,不过我暂时想不到其他方法了,后期再优化吧。
3)代码
public static int threeSumClosest(int[] nums, int target) {
int length = nums.length;
// 数组排序
Arrays.sort(nums);
String result = null;
for (int i = 0; i < length; i++) {
int j = i+1;
int k = length-1;
while (j<k) {
int sum = nums[i]+nums[j]+nums[k];
if (sum == target) { // 与目标值相等,直接返回
//System.out.println("sum = 0"+nums[i]+"+"+nums[j]+"+"+nums[k] + "=" + sum);
return sum;
}else {
//System.out.println(nums[i]+"+"+nums[j]+"+"+nums[k] + "=" + sum);
if (result == null) {
result = String.valueOf(sum);
} else {
// 当前差值
int absNow = Math.abs(sum - target);
// 存储的最小差值
int abs = Math.abs(Integer.parseInt(result) - target);
result = absNow < abs ? String.valueOf(sum) : result;
}
if (sum < target) {
while (j<k && nums[j] == nums[j+1]) j++; // 去重
j++;
}else {
while (j<k && nums[k] == nums[k-1]) k--; // 去重
k--;
}
}
}
while (i+1<length && nums[i] == nums[i+1]) i++; // 去重
}
return Integer.parseInt(result);
}
代码简化
public static int threeSumClosest(int[] nums, int target) {
int length = nums.length;
// 数组排序
Arrays.sort(nums);
// 最接近的和 初始化为前三个
int result = nums[0]+nums[1]+nums[2];
for (int i = 0; i < length; i++) {
int j = i+1;
int k = length-1;
while (j<k) {
int sum = nums[i]+nums[j]+nums[k];
// 与目标值相等,直接返回
if (sum == target) return sum;
result = Math.abs(sum - target) < Math.abs(result - target) ? sum : result;
if (sum < target) {
while (j<k && nums[j] == nums[j+1]) j++; // 去重
j++;
}else {
while (j<k && nums[k] == nums[k-1]) k--; // 去重
k--;
}
}
while (i+1<length && nums[i] == nums[i+1]) i++; // 去重
}
return result;
}
4)结果
代码简化结果: