题目:
给你一个长度为 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.com/problems/3sum-closest
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
结果:
添加退出条件前的结果是最后一条
上面三条是添加结束判断后的。
解题思路:
首先排序。
固定最小的那个值,然后用双指针判断中间值和最大的值。
循环结束条件:
1,最小值大于numsSize - 3,(构不成三个数)。
2,当前最小值开始的最小三个数相加大于target,且与target的差大于min。(说明无法再构成差距更小的三个数。)
3,三个数相加正好等于target。
代码:
int compar(const void* a, const void *b) {
return *(int *)a - *(int *)b;
}
int threeSumClosest(int* nums, int numsSize, int target){
qsort(nums, numsSize, sizeof(int), compar);
int min = 1000; // 取大一点确保第一次算到tempAbs的时候能够赋值就可以
int retSum = target;
// 枚举固定其中一个,另外两个用双指针。
for (int i = 0; i < numsSize - 2; i++) {
int tweTarget = target - nums[i];
// 如果当前i开始最小三个数相加大于target且差距大于min,那么再怎么循环也无法得到小于min的结果,退出枚举
int minSum = nums[i] + nums[i + 1] + nums[i + 2];
if (minSum > target && minSum - target > min) {
break;
}
for (int left = i + 1, right = numsSize - 1; left < right; ) {
// 判断三个值相加是否是比历史更靠近target
int tempSum = nums[left] + nums[right];
int tempAbs = abs(tempSum - tweTarget);
if (tempAbs < min) {
retSum = tempSum + nums[i];
min = tempAbs;
}
// 如果tempSum 已经等于target就退出
if (tempAbs == 0) {
break;
}
// 移动left or right
if (tempSum < tweTarget) {
left++;
} else {
right--;
}
}
if (min == 0) {
break;
}
}
return retSum;
}