题目描述:给你一个长度为
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
-10^4 <= target <= 10^4
双指针
- 外层循环从数组的第一个元素开始遍历到倒数第三个元素,
k
是第一个指针 - 内层循环使用两个指针
i
和j
分别指向k+1
和最后一个元素,用于查找另外两个数 - 在每一次循环中,计算三数的和
sum
,并更新closest
值,使其更接近目标值 - 如果
sum
大于目标值target
,则减小j
指针来减小sum
;如果sum
小于目标值target
,则增加i
指针来增大sum
- 如果
sum
等于target
,则直接退出内层循环,因为已经找到了一个完美匹配的答案
使用双指针和排序的技巧来解决,时间复杂度为O(n^2),其中n是数组的长度。
class Solution {
public int threeSumClosest(int[] nums, int target) {
int closest = nums[0] + nums[1] + nums[2];
if (nums.length == 3) return closest;
Arrays.sort(nums);
for (int k = 0; k < nums.length - 2; k++) {
int i = k + 1;
int j = nums.length - 1;
while (i < j) {
int sum = nums[k] + nums[i] + nums[j];
if (Math.abs(target - closest) > Math.abs(target - sum)) closest = sum;
if (sum > target) {
// 跳过所有重复的nums[j]
while (i < j && nums[j] == nums[--j]) ;
} else if (sum < target) {
// 跳过所有重复的nums[i]
while (i < j && nums[i] == nums[++i]) ;
} else {
break;
}
}
}
return closest;
}
}