题目链接
相似题目:Leetcode-15 三数之和
排序+双指针
对数组nums排序,锁定一个数字nums[i],再使用双指针考虑剩下的两数之和
双指针初始化:lf=i+1(不用再从头开始,如果有这个组合在i更小就会被发现的)
对于每一个ans取值,比较res和ans谁和target差绝对值更小.
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int res=INT_MAX/2;
int lf,rt;
for(int i=0;i<nums.size();i++)
{
lf=i+1;
rt=nums.size()-1;
while(lf<rt)
{
int ans=nums[i]+nums[lf]+nums[rt];
if(ans==target)
{
return target;
}
else if(ans<target)
{
res=fabs(res-target)>fabs(ans-target)?ans:res;
lf++;
}
else
{
res=fabs(res-target)>fabs(ans-target)?ans:res;
rt--;
}
}
}
return res;
}
};
考虑去重
对于nums[i]的去重
当i比较小时,剩下两个数的考虑范围是更大的。
比如对于[1,1,1,2,3],target=7
这一组来讲,对于第一个1,便会从[1,1,2,3]
中找到最合适的[2,3]
,第二个1和第三个1只是搜索的范围在减小,所以可以考虑去重。
对于nums[lf]与nums[rt]的去重
同理,假设输入变为[1,1,1,3,3,3],target=6
.
对于第一个1,在[1,1,3,3,3]
中查到的第一组便是nums[lf]=1, nums[rt]=3
之后搜索范围向内收紧,但是如果nums[lf]或是nums[rt]值与上一次不变,那么就没必要再次加和求ans,只有变化值才有可能带来更接近的结果
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int res=INT_MAX/2;
int lf,rt;
for(int i=0;i<nums.size();i++)
{
if(i>0&&nums[i-1]==nums[i])
continue;
lf=i+1;
rt=nums.size()-1;
while(lf<rt)
{
int ans=nums[i]+nums[lf]+nums[rt];
if(ans==target)
return target;
res=fabs(res-target)>fabs(ans-target)?ans:res;
if(ans<target)
{
lf++;
while(lf<rt&&nums[lf]==nums[lf-1])
lf++;
}
else
{
rt--;
while(lf<rt&&nums[rt]==nums[rt+1])
rt--;
}
}
}
return res;
}
};