一、概述
给定一个数组和一个指定数target,在数组中找出三个数,它们的和最接近target。输出三个数之和。
思想与3sum类似,我答的最好的一道题。
原创加两个100,开心。
二、分析
就只描述我自己的思路了,膨胀。
整个外壳还是类似3sum,遍历整个数组,取left和right两个指针,三个数相加,大于则right--,小于则left++。
关键在于大于和小于,我们知道,“最接近”可以是大于也可以是小于,因此,如果只维护一个“当前最接近”,那么每次都要比较三个数的和与target的差,和当前最接近于target的差,然后选择是否更新当前最接近。这样很麻烦,也没有利用排序的性质。
我们选择储存两个“当前最接近”,,一个是小于target的,一个是大于target的,这样一来,在执行right--之后,我们一定有此三个数的和大于target,那么直接判断并更新ans2即可,同理判断并更新ans1。
最后选择两个中的一个输出即可。
三、总结
分情况讨论可以很好地解决该问题。遇到可能大于可能小于的情况,不如将其归类为两大类,然后分别处理,最后判断结果。
PS:代码如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
if(nums.size()==3)
return nums[0]+nums[1]+nums[2];
else
{
sort(nums.begin(),nums.end());
int ans1=INT_MAX,ans2=INT_MIN;
for(int i=0;i<nums.size();i++)
{
int left=i+1,right=nums.size()-1;
while(left<right)
{
int sum=nums[left]+nums[right];
if(sum+nums[i]>target)
{
right--;
if(sum+nums[i]<ans1)
ans1=sum+nums[i];
}
else if(sum+nums[i]<target)
{
left++;
if(sum+nums[i]>ans2)
ans2=sum+nums[i];
}
else
return target;
}
}
if(ans1==INT_MAX)
return ans2;
else if(ans2==INT_MIN)
return ans1;
else
return (ans1-target)>(target-ans2)?ans2:ans1;
}
}
};