16. 最接近的三数之和

本文介绍了解决编程问题,给定一个整数数组nums和目标值target,通过使用多指针策略和排序找出三个数之和与target最接近的解。作者提供了两种解题思路并给出了优化后的代码示例。
摘要由CSDN通过智能技术生成

引流:五点钟科技-CSDN博客 

题目:

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。

返回这三个数的和。

假定每组输入只存在恰好一个解。

【解题思路】

遇到这种x数之和的问题,不要纠结,优先考虑多指针的解法。本题和【三数之和 】并没有本质上的区别,唯一的区别在于其判断条件变了,这里是要在数组中寻找3个数之和与某个数的距离,在三数之和的题中,是寻找三个数与0之间的关系,很明显的,当target为0时,题目就蜕变成三数之和的问题了,只不过此处是求最“接近”而非“等于”。

既然如此,我们只需要在三数之和的判断条件中,将if的左边项减去一个target,右边仍然保持为0,形式上就还是三数之和的“三段式判别法”,即<0的情况、>0的情况以及=0的情况,这是在判断什么呢?当然是判断第二个指针和第三个指针如何移动的问题啦,显然,当三数之和与target的差值为负数时,说明差值过大,所以第二个指针需要往大的方向移动(向右移动),当三数之和与target的差值为正数时,同理需要第三个指针向左移动,当差值为0时,两个指针同时向内移动一步。那么“最接近”该怎么判断呢?也很好理解,既然是最接近,那必然是求距离的问题,要求最小距离,我们设置一个变量minx来始终记录距离最小的值,因此我们只需要在三段式判别之下再多一个判断,即判断当前三数之和与target之差的绝对值是否小于minx即可,显然,当当三数之和与target的差值为0时,说明三数之和直接等于target,距离达到最小,为0,那么minx就为0。

【代码】

def threeSumClosest(self, nums: List[int], target: int) -> int:
        if len(nums) == 3:
            return sum(nums)
        n = len(nums)-1
        minx = float('inf')
        nums.sort()
        for cur in range(n-1):
            left = cur + 1
            right = n
            while left < right:
                if nums[cur] + nums[left] + nums[right] - target < 0:
                    if abs(nums[cur] + nums[left] + nums[right] - target) < minx:
                        minx = abs(nums[cur] + nums[left] + nums[right] - target)
                        res = nums[cur] + nums[left] + nums[right]
                    left += 1
                elif nums[cur] + nums[left] + nums[right] - target == 0:
                    minx = 0
                    res = nums[cur] + nums[left] + nums[right]
                    left += 1
                    right -= 1
                else:
                    if abs(nums[cur] + nums[left] + nums[right] - target) < minx:
                        minx = abs(nums[cur] + nums[left] + nums[right] - target)
                        res = nums[cur] + nums[left] + nums[right]
                    right -= 1
        return res

为了更好的理解,上述代码有许多啰嗦的地方,特别是判断与0大小关系的条件的地方,其实完全可以合并成与target判断大小关系。而且这里要注意,题目有个很友好的限制条件,那就是每个数组只存在一个答案,所以上述代码实际上可以进一步优化:

def threeSumClosest(self, nums: List[int], target: int) -> int:
        if len(nums) == 3:
            return sum(nums)
        size = len(nums)
        nums.sort()
        diff = float('inf')
        res = 0
        for p in range(size-2):
            if p and nums[p] == nums[p-1]:
                continue
            left, right = p+1, size-1
            while left < right:
                cur = nums[left] + nums[right] + nums[p]
                if cur == target:
                    return target
                if abs(cur - target) < diff:
                    diff = abs(cur - target)
                    res = cur
                if cur < target:
                    left += 1
                else:
                    right -= 1
        return res

这样代码简洁多了。 

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五点钟科技

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值