力扣(LeetCode)试题--最接近的三数之和 c++实现

3Sum Closest(最接近的三数之和)

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

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

示例:

输入:nums = [-1,2,1,-4], target = 1
输出:2
解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。

算法1:暴力求解

将所有可能的三个数的组合穷举出来,然后依次计算与target最接近的和

int diff(const int& v1,const int&v2) {
    int re = v1 - v2;
    return re > 0 ? re : -re;
}

int threeSumClosest1(vector& nums, int target) {
    int sum = 0;
    int sum_temp;
    int diff_min = INT16_MAX;
    vector::iterator begin = nums.begin();
    vector::iterator end = nums.end();

    for (vector::iterator i=begin; i != end - 2; i++) {
        for (vector::iterator j = i + 1; j != end - 1; j++) {
            for (vector::iterator k = j + 1; k != end; k++) {
                sum_temp = *i + *j + *k;
                int dif_temp = this->diff(sum_temp, target);
                if (dif_temp==0)
                {
                    return sum_temp;
                }
                if (dif_temp

算法优化

先对数据按照升序排序,假设在一次循环中,得到的三个数之和与target的差>0,则最内层循环没有必要继续进行,因为继续循环下去后面的三个数之和与target差值都会大于当前的差值

int diff(const int& v1,const int&v2) {
    int re = v1 - v2;
    //return re > 0 ? re : -re;
    return re;
}
int threeSumClosest2(vector& nums, int target) {
    int sum = 0;
    int sum_temp;
    int diff_min = INT16_MAX;
    vector::iterator begin = nums.begin();
    vector::iterator end = nums.end();
    sort(begin, end);

    for (vector::iterator i = begin; i != end - 2; i++) {
        for (vector::iterator j = i + 1; j != end - 1; j++) {
            for (vector::iterator k = j + 1; k != end; k++) {
                sum_temp = *i + *j + *k;
                int dif_temp = this->diff(sum_temp, target);
                if (dif_temp==0)
                {
                    return sum_temp;
                }

                if (abs(dif_temp) < abs(diff_min))
                {
                    diff_min = dif_temp;
                    sum = sum_temp;
                }

                if (diff_min>0 && dif_temp>diff_min)
                {
                    break;
                }

            }
        }
    }

    return sum;

}

使用暴力求解的算法时间复杂度为 O ( n 3 ) O(n^3) O(n3)

算法2:双指针

为了减少算法的时间复杂度,可以考虑使用双指针,将算法的三层循环编程双层循环

先对数组升序排序

设三个数的指针分别为 i . j , k i.j,k i.j,k

  • 固定 i = v [ 0 ] i=v[0] i=v[0],考虑其他两个数的位置
  • j = i + 1 , k = n j=i+1,k=n j=i+1,k=n
  • 判断当前的三个数之和 s u m sum sum
    • sum
    • sum>target k– :即如果三数之和比target大,则差异更小的数只可能在[j,k-1]之间产生
  • 记录每次组合的三数之和,更新当前最小和

这样,当一个数固定下来之后,另外两个数的可能产生差异最小的组合通过扫描一次数组就可以完成,即线性时间复杂度,对第一个数枚举,整个算法的复杂度为 O ( n 2 ) O(n^2) O(n2)

力扣(LeetCode)试题--最接近的三数之和 c++实现_第1张图片

int diff(const int& v1,const int&v2) {
    int re = v1 - v2;
    //return re > 0 ? re : -re;
    return re;
}

int threeSumClosest3(vector& nums, int target) {
    int sum = 0;
    int sum_temp;
    int diff_temp;
    int diff_min = INT16_MAX;
    vector::iterator begin = nums.begin();
    vector::iterator end = nums.end();
    sort(begin, end);

    for (vector::iterator i = begin; i != end - 2; i++) {
        vector::iterator j = i + 1;
        vector::iterator k = end - 1;
        while (j!=k)
        {
            sum_temp = *i + *j + *k;
            diff_temp = diff(sum_temp, target);


            if (diff_temp == 0)
            {
                return sum_temp;
            }

            if (abs(diff_temp)

算法性能对比

算法 时间 内存
暴力求解 1896ms 9.9MB
双指针 16ms 10.3MB

你可能感兴趣的:(每天一点点算法)