LeetCode-16-最接近的三数之和


题意描述:

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


示例:

例如,给定数组 nums = [-121-4], 和 target = 1. 
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

解题思路:

Alice: 三重循环应该不行吧,会超时吧。
Bob: 不知道哦,我们可以试试看,而且应该能优化一些的。
Alice: 三数之和与 target 最接近的时候,两者的差值应该就是 0,这一点可以直接优化。

10 mins later;
Bob: Amazing 😮,三重循环加一点优化居然可以啊。
Alice: 排序 + 双指针应该也可以。就是三数之和那题一样。
Bob: 应该是可以的,外层循环遍历三元组中最小的元素,然后用双指针从两个方向把 三元组之和 逼近 target 目标值。
Alice: 对对对,这样可以减少 搜索 三元组 的次数,只需要每次移动双指针的时候检测 三元组的值就行了。
Bob: 😎😎


代码:
Python 方法一: 三重循环 + 一点点优化,竟然也能过,Amazing ! 😮

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:

        minValue = 2147483647
        for x in range(len(nums)):
            for y in range(x+1, len(nums)):
                for z in range(y+1, len(nums)):
                    tmp = abs(nums[x] + nums[y] + nums[z] - target) 
                    if tmp < minValue:
                        minValue = tmp
                        ret  = nums[x] + nums[y] + nums[z]
                    if minValue == 0:
                        return ret
        return ret

Java 方法一: 三重循环,竟然通过了。Amazing ! 😮

class Solution {
    public int threeSumClosest(int[] nums, int target) {

        int tmp = 0;
        int ans = 0;
        int minValue = 2147483647;

        for(int i=0; i<nums.length; ++i){
            for(int j=i+1; j<nums.length; ++j){
                for(int k=j+1; k<nums.length; ++k){
                    tmp = abs(nums[i] + nums[j] + nums[k] - target);
                    if(tmp < minValue){
                        minValue = tmp;
                        ans = nums[i] + nums[j] + nums[k];
                    }
                    if(minValue == 0){
                        return ans;
                    }
                }
            }
        }
        return ans;
    }

    public int abs(int a){
        if(a < 0){
            a *= -1;
        }
        return a;
    }
}

Python 方法二: 排序 + 双指针 ,通过。

class Solution:
    def threeSumClosest(self, nums: List[int], target: int) -> int:

        nums.sort()
        ans = 0
        minValue = 2147483647

        for x in range(len(nums)):       # 假设最外层遍历的是 三元组 中最小的元素

            left  = x + 1
            right = len(nums) - 1
            tmp  = 0

            while left < right:
                tmp = nums[x] + nums[left] + nums[right]
                if tmp == target:
                    return target
                elif tmp > target:
                    right -= 1
                else:
                    left  += 1

                if abs(tmp - target) < minValue:
                    minValue = abs(tmp - target)
                    ans = tmp

        return ans

Java 方法二: 排序 + 双指针。

class Solution {
    public int threeSumClosest(int[] nums, int target) {

        Arrays.sort(nums);
        int ans   = 0;
        int left  = 0;
        int right = 0;
        int tmpSum  = 0;
        int tmpDiff = 0;
        int minValue = 2147483647;

        for(int i=0; i<nums.length; ++i){

            left  = i + 1;
            right = nums.length - 1;
            while(left < right){
                tmpSum = nums[i] + nums[left] + nums[right];
                if(tmpSum == target){
                    return target;
                }else if(tmpSum < target){
                    left += 1;
                }else{
                    right -= 1;
                }
                tmpDiff = abs(tmpSum - target);
                if(tmpDiff < minValue){
                    minValue = tmpDiff;
                    ans = tmpSum;
                }
            }
        }
        return ans;
    }

    public int abs(int a){
        if(a < 0){
            a *= -1;
        }
        return a;
    }
}

易错点:

  • 可能超时的点:
[-26,84,-85,2,99,42,-28,16,-97,-59,64,-67,-30,18,-15,-11,-60,-79,41,-29,49,-33,21,-8,-73,6,-31,31,-23,82,-34,12,86,38,-4,99,4,63,-13,-42,-4,89,88,-30,0,15,37,-95,-85,15,66,8,43,95,-76,75,-16,48,15,-82,56,83,91,81,-76,-29,7,-77,-42,39,-73,29,43,-60,21,-5,-3,1,32,34,-77,49,68,-1,-63,93,-20,-57,-65,53,23,96,79,87,-12,-18,51,39,-24,27,13,-55,-6,28,95,91,-71,77,49,-26,-17,-83,43,-86,28,20,64,-6,53,40,81,-30,-83,67,-3,25,37,54,95,14,84,-96,76,15,35,41,-86,33,10,-32,59,100,30,-9,58,-80,23,20,43,93,58,-26,37,44,-24,27,99,-46,-80,-85,-44,-45,-72,-32,33,-24,91,-67,75,-40,52,49,94,-10,82,-76,-92,58,18,-43,47,-75,-17,-30,-17,-57,37,51,-32,69,54,-71,-98,-74,-17,99,84,-67,80,-24,-100,98,19,99,-7,-98,-43,73,-97,-21,96,-44,59]
-186
  • 答案:
-186

总结:

咔嚓,(^_-)
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值