16. 最接近的三数之和 - 力扣(LeetCode)

题目描述

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。 例如,给定数组 nums = [-1,2,1,-4], 和 target = 1. 与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

题解

最容易想到的方法,肯定是三重循环,暴力求解,但是时间复杂度过高为[latex] O(n^3) [/latex]。 这里借鉴昨天三数之和那一题的解题思路,采用排序+双指针的方法来求解,同样a固定,然后首尾指针分别指向b与c,当a+b+c=target,则最优解就是target。若a+b+c>target,指向c的指针向左移动;若a+b+c<target,指向b的指针向右移动。当两指针相遇本次循环结束,然后更改a的位置,重复上述操作,直到找到最优解。 起初,天真的以为当sum(a+b+c)由大于target转为小于target或者由小于target转为大于target时,就能找到本次循环的最优解,就能跳出循环,后来提交才发现并不是,所以还是老老实实的判断吧。

错误代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int len = nums.size(), beg, end, sum, res;
bool posFlag = false, negFlag = false, flag = false;;
int posSum, negSum;
for(int i =0; i < len - 2; ++i){
if(i > 0 && nums[i] == nums[i - 1]){//去重
continue;
}
beg = i + 1, end = len - 1;
posFlag = false, negFlag = false;
while(beg < end){
sum = nums[i] + nums[beg] + nums[end];
if(sum > target){
--end;
posFlag = true;
posSum = sum;
}
else if(sum < target){
++beg;
negFlag = true;
negSum = sum;
}
else{
res = target;
flag = true;
break;
}
if(posFlag && negFlag){
if(!flag){
flag = true;
res = posSum - target > target - negSum?negSum:posSum;
}
else{
int tmp = posSum - target > target - negSum?negSum:posSum;
res = abs(tmp - target) > abs(res - target)?res:tmp;
}
break;
}
}
if(flag && res == target){
break;
}
if(posFlag && !negFlag){//全大于target,取最小
if(i + 2 < len){
if(!flag){
flag = true;
res = nums[i] + nums[i + 1] + nums[i + 2];
}
else{
int tmp = nums[i] + nums[i + 1] + nums[i + 2];
res = abs(tmp - target) > abs(res - target)?res:tmp;
}
}
}
else if(negFlag && !posFlag){//全小于target,取最大
if(i + 2 < len){
if(!flag){
flag = true;
res = nums[i] + nums[len - 1] + nums[len - 2];
}
else{
int tmp = nums[i] + nums[len - 1] + nums[len - 2];
res = abs(tmp - target) > abs(res - target)?res:tmp;
}
}
}
if(flag && res == target){
break;
}
}
return res;
}
};
///未ac

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int len = nums.size(), beg, end, sum, res;
for(int i =0; i < len - 2; ++i){
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
if(i == 0){
res = nums[0] + nums[1] +nums[2];
}
beg = i + 1, end = len - 1;
while(beg < end){
sum = nums[i] + nums[beg] + nums[end];
if(abs(sum - target) < abs(res - target)){//取距离较小的
res = sum;
}
if(sum > target){//偏大,减小end
--end;
}
else if(sum < target){//偏小,增大beg
++beg;
}
else{//相等,找到最优解,直接返回
return res;
}
}
}
return res;
}
};

执行结果