暴力代碼:
#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)
從這個題我學到了:
- 雙指針