题目
给你一个长度为 n
的整数数组 nums
和 一个目标值 target
。请你从 nums
中选出三个整数,使它们的和与 target
最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-104 <= target <= 104
示例
示例 1:
输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1 输出:0
解题思路及代码
方法一:暴力搜索
不考虑时间代价,直接采用暴力搜索的方式,三层for循环嵌套逐渐缩小sum与target之间的差距,最终找出与target最近的sum。(无脑流不推荐!!!)
完整代码如下:
#include<iostream>
#include<cstdlib>
#include<vector>
using namespace std;
int threeSumClosest(vector<int>& nums, int target){
int n = nums.size();
int res = 0;
int diff = INT_MAX;
for(int i = 0; i < n; i++){
for(int j = i + 1; j < n; j++){
for(int k = j + 1; k < n; k++){
int sum = nums[i] + nums[j] + nums[k];
if(abs(target - sum) < diff){
diff = abs(target - sum);
res = sum;
}
}
}
}
return res;
}
int main(void){
vector<int> nums = {-1,2,1,-4};
int target = 1;
cout << threeSumClosest(nums, target) << endl;
system("pause");
return 0;
}
方法二:排序+双指针
这个题目其实可以参考我在上一篇《15.三数之和》中提到的一个方法,采用排序+双指针的方式。
首先还是要对数组进行一个排序,然后对数组中的每一个值nums[i]进行遍历。
遍历时设置两个指针,一个指向i+1的位置,一个指向nums.size()-1的位置。
这时我们就可以根据sum=nums[i]+nums[start]+nums[end]的结果来进行讨论,讨论他和target之间的大小关系,
- 如果sum比较大,就需要将右指针向前移。
- 如果sum比较小,就需要将左指针向后移。
- 如果sum和target相等了,就可以直接返回了(题目条件:假定每组输入只存在恰好一个解!!!)。
以下是完整代码:
#include<iostream>
#include<cstdlib>
#include<vector>
#include<algorithm>
using namespace std;
int threeSumClosest(vector<int>& nums, int target){
int n = nums.size(); // 数组长度
sort(nums.begin(), nums.end()); // 排序
int ans = nums[0] + nums[1] + nums[2];
for(int i = 0; i < n; i++){
int start = i + 1, end = n - 1; // 双指针
while(start < end){
int sum = nums[i] + nums[start] + nums[end];
if(abs(target - sum) < abs(target - ans)){ // 三数之和与目标值的差值绝对值小于当前最小差值,更新最小差值
ans = sum;
}
if(sum > target){ // 三数之和大于目标值,右指针左移
end--;
}else if(sum < target){ // 三数之和小于目标值,左指针右移
start++;
}else{ // 三数之和等于目标值,直接返回
return ans;
}
}
}
return ans;
}
int main(void){
vector<int> nums = {-1,2,1,-4};
int target = 1;
cout << threeSumClosest(nums, target) << endl;
system("pause");
return 0;
}