暴力代码:
#include<math.h>
int threeSumClosest(int* nums, int numsSize, int target){
int sum = 0;
int temp = ((unsigned)(-1)) >> 1;// 表示三个数的和与target的差值
int i = 0, j = 0, k = 0;
for (i = 0;i < numsSize; i++) {
for (j = i + 1; j < numsSize; j++) {
for (k = j + 1; k < numsSize; k++) {
if (abs(nums[i] + nums[j] + nums[k] - target) < temp) {
temp = abs(nums[i] + nums[j] + nums[k] - target);
sum = nums[i] + nums[j] + nums[k];
}
}
}
}
return sum;
}
优化代码(排序+双指针):
#include<math.h>
void sort(int* nums, int numsSize) {
int i = 0, j = 0;
int temp = 0;
for (i = numsSize - 1; i > 0; i--) {
for (j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
}
/*
算法概述:排序+双指针
遍历nums的每一个元素时候,根据sum和target的大小关系调整
start和end的指向,让sum有可能和target更接近,同时更新结果
这样一来遍历一遍之后就能找到最接近的和
*/
int threeSumClosest(int* nums, int numsSize, int target){
long sum = 0;// 三个数的和
long res = ((unsigned)(-1)) >> 1;// 最接近的和
int i = 0, start = 0, end = 0;// 三个数的下标
sort(nums, numsSize);// 排序
for (i = 0; i < numsSize; i++) {
start = i + 1;// 初始化双指针
end = numsSize - 1;
while (start < end) {// 开始调整两个指针的位置
sum = nums[i] + nums[start] + nums[end];
if (labs(sum - target) < labs(res - target))
res = sum;// 更新结果
if (sum > target)
end--;// 这种情况下只有后一个指针往前移才可能使得三个数的和更接近target
else if (sum < target)
start++;// 这种情况下只有前一个指针往前移才可能使得三个数的和更接近target
else
break;
}
}
return res;
}
这里有两个点真是妙啊:
- 双指针的手法
- “有可能会更好,但不一定会更好”这个思想
不过这里有个坑:
如果res和target全为int型的话abs(res - target)可能会超出int范围,比如INT_MAX - (-100)
从这个题我学到了:
- 双指针