题目描述
给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
3 <= nums.length <= 10^3
-10^3 <= nums[i] <= 10^3
-10^4 <= target <= 10^4
解题思路
这道题和15题非常类似,15题问的是三数和为0,而这里是寻找三个数和与目标最接近的情况。首先还是会想到暴力解法,时间复杂度达到了O(n^3)。
1. 枚举法
int threeSumClosest(vector<int>& nums, int target) {
int i=0,j=0,k,min=1000000,ap=0,ans;//min存放差最小值,ans输出最后的答案
vector<int> temp;
sort(nums.begin(),nums.end());
for(i=0;i<nums.size();i++){
for(j=i+1;j<nums.size();j++){
k=nums.size()-1;
while(j<k)
{
ap=abs(nums[i]+nums[j]+nums[k]-target);
if(ap<min)
{min=ap;
ans=nums[i]+nums[j]+nums[k];}
k--;
}
}
}
return ans;
}
这里的写法有一些借鉴了15题,没有写三重循环,但是其实k也是参与循环了。这个代码刚好可以通过,但是时间耗时较长,需要进行优化。
2. 排序+双指针
与15题一样,先进行排序,然后使用双指针。但是使用的时候需要注意一下,这里的判断条件略有不同:
如果a+b+c≥target,那么就将k向左移动一个位置
如果a+b+c<target,那么就将j向右移动一个位置
这样可以保证和越来越接近target。求每次的值并取最小:
int threeSumClosest(vector<int>& nums, int target) {
int i=0,j=0,k,min=1000000,ap=0,ans;
vector<int> temp;
sort(nums.begin(),nums.end());
for(i=0;i<nums.size();i++){
k=nums.size()-1;
for(j=i+1;j<nums.size();j++){
while(j<k)
{
ap=abs(nums[i]+nums[j]+nums[k]-target);
if(ap<min)
{min=ap;
ans=nums[i]+nums[j]+nums[k];}
if(nums[i]+nums[j]+nums[k]<target){//增加了这个的判断,提高效率
j++;
}
else k--;
}
}
}
return ans;
}