输入: nums整数数组
输出: 三数之和的整数
要求: 和最接近给出的target
难度: 中等
思路:
首先先排一个序把。
然后假设先按照3sum的思路,使用三个指针来代表三个数(abc)。对a在数组进行循环,然后bc从两端开始往中间走。b从a开始,c是最右边。令i=a+b+c-target, 如果i>0 那么c往左走, 不然c往左走,如果等于0就输出target。 当i的符号改变时,符号改变前后的数字都可能是c的候选者。当bc相等时,进入下一个a的循环。
对于重复的数,a循环遇见之后往后走。b往右走,c往左走。
int closerToTarget(int a, int b, int c, int target){
int num = 0;
if(abs(a-target) > abs(b-target)){
if(abs(b-target)> abs(c-target)){
num = c;
}else{
num = b;
}
}else if(abs(a-target) > abs(c-target))
num = c;
else
num = a;
return num;
}
int threeSumClosest(vector<int>& nums, int target) {
int size = nums.size();
if(size <3) return 0;
sort(nums.begin(),nums.end());
int sum = nums[0]+nums[1]+nums[2]; //最后的三数和
int a = 0, b = 0, c = 0; //num[a], num[b], num[c]
while(a < size - 2){
int twoTarget = target - nums[a];
int flag = 0, tempflag = 0;
for(b = a+1, c = size-1;b<c;){
flag = nums[b] + nums[c] - twoTarget;
sum = closerToTarget(flag+target, sum, sum, target);
if(flag > 0){
tempflag = nums[c];
do{
c--;
}while(c > b && tempflag == nums[c]);
}else if(flag <0){
tempflag = nums[b];
do{
b++;
}while(b<c && tempflag == nums[b] );
}else{
return target;
}
tempflag = nums[b]+nums[c]-twoTarget;
if(flag*tempflag<0){
sum = closerToTarget(flag+target, tempflag+target, sum, target);
}
}
tempflag = nums[a];
do{
a++;
}while(a< size - 2 && tempflag == nums[a] );
}
return sum;
}
执行用时 : 24 ms, 在3Sum Closest的C++提交中击败了20.07% 的用户
内存消耗 : 9.4 MB, 在3Sum Closest的C++提交中击败了0.33% 的用户
下面来看执行速度为8ms的范例:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int min=nums[0]+nums[1]+nums[2];
for(int i=0;i<nums.size()-2;i++)
{
int a=i+1;
int b=nums.size()-1;
while(a<b)
{
int sum=nums[i]+nums[a]+nums[b];
if(abs(sum-target)<abs(min-target))
{
min=sum;
}
if(sum>target)
{
b--;
}
else if(sum<target)
{
a++;
}
else
{
return target;
}
}
}
return min;
}
执行用时 : 16 ms, 在3Sum Closest的C++提交中击败了30.57% 的用户
内存消耗 : 9.4 MB, 在3Sum Closest的C++提交中击败了0.33% 的用户
起码比我稳定地快。分析它的代码,核心思路一样。我多进行了判断,符号变化地错误,应该直接进行比较。有可能从头到尾都没有变化。而且比较产生地时间远小于判断符号消耗地时间,因此最后得到了:
int threeSumClosest(vector<int>& nums, int target) {
int size = nums.size();
if(size <3) return 0;
sort(nums.begin(),nums.end());
int sum = nums[0]+nums[1]+nums[2];
int a = 0, b = 0, c = 0;
while(a < size - 2){
int twoTarget = target - nums[a];
int flag = 0, temp = 0;
for(b = a+1, c = size-1;b<c;){
flag = nums[b]+nums[c] - twoTarget;
if(abs(flag) < abs(sum - target)){
sum = nums[b]+nums[c]+nums[a];
}
if(flag > 0){
temp = nums[c];
do{
c--;
}while(c > b && temp == nums[c]);
}else if(flag <0){
temp = nums[b];
do{
b++;
}while(b<c && temp == nums[b] );
}else{
return target;
}
}
temp = nums[a];
do{
a++;
}while(a< size - 2 && temp == nums[a] );
}
return sum;
}
比上面地人多做了大数字跳过。