给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。
返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1
输出:0
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-104 <= target <= 104
通过次数322,952提交次数705,444
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum-closest
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
首先这道题如果不对这个数组进行处理的话,就只能用三个循环去遍历,时间复杂度是
O
(
n
3
)
O(n^3)
O(n3),但是我们可以先对数组进行排序,再用双指针的方法去遍历,时间复杂度是
O
(
n
2
)
O(n^2)
O(n2)。
代码如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int best=1e7;
auto f=[&](int ctr)
{
if(abs(ctr-target)<abs(best-target))
{
best=ctr;
}
};
int i=0;
for(;i<nums.size();i++)
{
if(i>0&&nums[i]==nums[i-1])
{
continue;
}
int j=i+1;
int k=nums.size()-1;
while(j<k)
{
int ctr=nums[i]+nums[j]+nums[k];
if(ctr==target)
{
return target;
}
f(ctr);
if(ctr>target)
{
--k;
while(k>j&&nums[k+1]==nums[k])
{
--k;
}
}else if(ctr<target)
{
j++;
while(j<k&&nums[j]==nums[j-1])
{
++j;
}
}
}
}
return best;
}
};
auto f=[&](int ctr)
这是个匿名函数
Lambda 表达式的定义形式如下:
[外部变量访问方式说明符] (参数表) -> 返回值类型
{
语句块
}
其中,“外部变量访问方式说明符”可以是=或&,表示{}中用到的、定义在{}外面的变量在{}中是否允许被改变。=表示不允许,&表示允许。当然,在{}中也可以不使用定义在外面的变量。“-> 返回值类型”可以省略。
auto f就是让这个匿名函数取个名字叫f。
这个函数的作用就是当我们遇到更合适的值时,进行更新。
然后我们定义变量i,对这个数组从下标0开始遍历。然后定义变量j=i+1,还有k=nums.size()-1,来表示左右指针,接下来就是双指针的常规做法,有一点需要注意的是:while(k>j&&num[k+1]==nums[k])这条语句的上一条语句是–k,这时候k已经减少一次了,而我们这个while循环是为了判断我原来的nums[k]是不是和下面的nums[k-1]相等,但是k已经减少了1,所以我们想要判断是不是和原来的k相等应该是k+1和k比较,这也是个易错点。