leetcode:16. 最接近的三数之和

题目来源

题目描述

在这里插入图片描述

题目解析

思路和leetcode:15. 三数之和一致。

首先考虑枚举第一个元素 a,对于剩下的两个元素 b 和 c,我们希望它们的和最接近 t a r g e t − a target−a targeta。因为此时b + c在数组中范围是没有任何规律的,所以我们只能有一个双重循环来枚举所有的可能情况。因此,我们可以考虑先对数据进行升序排序,这样:

  • 假设数组的长度为n,我们先枚举a,它在数组中的位置为i
  • 为了防止重复枚举,我们在位置 [ i + 1 , n ) [i +1, n) [i+1,n)的范围内枚举b和c。又因为数组是有序的,所以可以用双指针对这个枚举过程进行优化。我们用 p b p_b pb p c p_c pc分别指向b和c的位置。这样,初始时, p b p_b pb指向位置 i + 1 i + 1 i+1,即左边界; p c p_c pc指向 n − 1 n - 1 n1,即右边界。在枚举的每一个过程中,我们用 a + b + c a + b + c a+b+c来更新答案,并且:
  • 如果 a + b + c > = t a r g t e a + b + c >= targte a+b+c>=targte,那么 p c p_c pc左移
  • 如果 a + b + c < t a r g t e a + b + c < targte a+b+c<targte,那么 p b p_b pb右移
class Solution {
public:
    // 3 <= nums.length <= 1000
    int threeSumClosest(vector<int>& nums, int target) {
        std::sort(nums.begin(), nums.end());
        int  ans = 0;
        int m = nums.size();
        int min = INT_MAX;

        auto update = [&](int sum){
            int gap = abs(target - sum);  // 离target的距离越小越好
            if(gap < min){  //本次得到的距离比以前的最小距离还接近 . 那么更新 值
                min = gap; //更新最小窗口
                ans = sum; //更新ans
            }else{  // 本次离target的距离比上一次的大,那么什么也不做

            }
        };
        // 枚举 a
        for (int i = 0; i < m - 2; ++i) {  // m - 2是为了确保nums[i]后面一定有两个数
            // 保证和上一次枚举的元素不相等
            if(i > 0 && nums[i] == nums[i - 1]){
                continue;
            }
            int l = i + 1, r = m - 1;
            while (l < r){
                int sum = nums[l] + nums[r] + nums[i];  // sum 要最接近 target
                if(sum == target){
                    return target;
                }
                update(sum);
                if(sum > target){
                    --r;    // 往小的未搜索的那边走,并且不重复
                    while (l < r && nums[r] == nums[r + 1]){
                        --r;
                    }
                }else{
                    ++l;
                    while (l < r && nums[l] == nums[l - 1]){
                        ++l;
                    }
                }

            }
        }

        return ans;
    }
};

类似题目

题目核心思路
leetcode:15. 三数之和–>无序数组中选出三个数,令其和= 0,返回所有方案(去重) 3Sum先排序,然后定下第一个数(枚举),然后左右指针找另外两个数组,如果找到了sum=0的数就去重然后继续找(二分优化)
leetcode:16. 三数之和—>无序数组中选出三个数,最接近target的sum是什么 3Sum Closest先排序,然后固定第一个数(枚举),然后左右指针找另外两个数组,如果找到了sum==target就直接返回,如果找不到就缩小窗口以逼近target(二分优化)
leetcode:259. 三数之和–>无序数组中选出三个数,其和< target,返回所有的方案个数(不去重) 3Sum Smaller先排序,然后固定第一个数(枚举),然后双指针碰撞。将所有符合条件的[l,r]区间都算到结果里面。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值