LeetCode 16. 3Sum Closest

LeetCode 16. 3Sum Closest

题目要求:给出一个整型数组nums和一个整数target,要求从nums中找出3个整数a,b,c使得它们的和最接近target。
题目给出的框架如下所示:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {

    }
};

解题思路

这道题和之前的3Sum极为相似,原理参考上一篇文章LeetCode 15. 3Sum
只是条件有所改变从原来的nums[i]+nums[j]+nums[k]0的比较,变成了nums[i]+nums[j]+nums[k]target的比较。
但需要注意的是:3Sum的结果可以为空,本题的结果一定不为空,因此不能加上循环条件nums[k] < target/3
具体做法如下:

  1. 固定一个数k,在它后面找出两个数i=k+1和j=length-1,i和j不断向中间移动,使得nums[i]+nums[j]+nums[k]的值尽可能接近target,用minus记录targetnums[i]+nums[j]+nums[k]的差值,即:minus = target - nums[i] - nums[j] - nums[k]
  2. 为了使nums[i]+nums[j]+nums[k]的值尽可能接近target,因此,需要分为以下3种情况考虑:
    nums[i]+nums[j]+nums[k] == target,则直接返回nums[i]+nums[j]+nums[k]
    nums[i]+nums[j]+nums[k] < target,则为了使结果靠近target,应当使得i向右移动,nums[i]增大后,三者之和也相应的增大;
    nums[i]+nums[j]+nums[k] > target,则为了使结果靠近target,应当使得j向左移动,nums[j]减小后,三者之和也相应的减小;
  3. 为了剔除重复的情况,i和j在移动的时候碰到相同的元素应当继续向前移动,但是k不能,如果k碰到相同的就移动的话,可能会造成没有结果的情况,如nums={1,1,1,1}和targt=0

代码实现

代码实现如下:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        sort(nums.begin(), nums.end());
        int minus = INT_MAX;
        for (int k = 0; k < nums.size() - 2; ++k) {
            if (k > 0 && nums[k] == nums[k - 1])
                continue;
            int i = k + 1, j = nums.size() - 1;
            while (i < j) {
                if (abs(target - nums[i] - nums[j] - nums[k]) < abs(minus)) {
                    minus = target - nums[i] - nums[j] - nums[k];
                }
                if (nums[i] + nums[j] + nums[k] == target)
                    return target;
                if (nums[i] + nums[j] + nums[k] < target) {
                    while (++i < j && nums[i] == nums[i - 1])
                        ; // 跳过重复元素
                }
                if (nums[i] + nums[j] + nums[k] > target) {
                    while (i < --j && nums[j] == nums[j + 1])
                        ; // 跳过重复元素
                }

            }
        }
        return target - minus;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值