LeetCode算法题:最接近三数之和

题目描述如下:

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

       这道题我用两种方法做的,一种是暴力法,但是时间复杂度很高,暴力法的思路相信大家都知道,就是将所给数组中的任意三个数的值都算出来,然后选出值与target最接近的值,这个算法的时间复杂度可以用数学上排列组合中的组合方法来做,假设有所给数组中有n个元素,那么暴力法的时间复杂度为:n*(n-1)*(n-2),C43,时间复杂度是n的立方级,效率很低,下面给出暴力法的C++代码:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(),nums.end());
        if(nums.size()<3) return {};
        int closest=target+10000000;
        for(int i=0;i<nums.size()-2;i++)
        {
            int fix=nums[i];
            if(fix>target&&abs(fix+nums[i+1]+nums[i+2]-target)>abs(closest-target)) break;
            //这句话能够省略很多无用功
            for(int j=i+1;j<nums.size()-1;j++)
            {
                for(int k=j+1;k<nums.size();k++)
                {
                    int temp=abs(target-fix-nums[j]-nums[k]);
                    if(temp<abs(closest-target))
                        closest=fix+nums[j]+nums[k];
                }
            }
        }
        return closest;
    }
};

       进阶的算法是双指针法,固定一个值,寻找另外两个值。C++代码如下:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        int len = nums.size();
        sort(nums.begin(),nums.end());//利用C++自带的快排函数进行排序
        if(len<3){//如果数组长度小于3,返回空值
            return {};
        }
        int closest=nums[0]+nums[1]+nums[2];//起始,假设距离target最近的和由排完序后的前三个数组成
        int cha=0;//存储差值
        for(int i=0;i<len;i++){
            int fix = nums[i];//固定一个值
            int left = i+1;//左指针
            int right = len-1;//右指针
            if(left>=right){break;}//如果指针碰撞,结束循环
            while(left<right){
                if(nums[left]+nums[right]+fix==target){return target;}//如果三个值的和恰好等于target,那么直接返回
                if(nums[left]+nums[right]+fix<target){//如果三个数的和小于target
                    cha = target - nums[left] - nums[right] - fix;
                    if(cha<abs(closest-target)){//判断这三个数的和是否距离target更近
                        closest = nums[left]+nums[right]+fix;
                    }
                    left++;//三个数的值小于target,如果要寻找更接近target的元素,就需要寻找更大的元素,所以应该左指针向右移
                }
                else if(nums[left]+nums[right]+fix>target){//如果三个数的和大于target
                    cha = nums[left]+nums[right]+fix - target;
                    if(cha<abs(closest-target)){//判断这三个数的和是否距离target更近
                        closest = nums[left]+nums[right]+fix;
                    }
                    right--;/三个数的值大于target,如果要寻找更接近target的元素,就需要寻找更小的元素,所以应该右指针向左移
                }
            }
        }  
        return closest;//返回结果
    }
};

如果有写的不对的地方,还请各位朋友批评指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值