来自北大算法课的Leetcode题解:16. 最接近的三数之和

代码仓库Github | Leetcode solutions @doubleZ0108 from Peking University.

最直观的想法是先排序,然后一次遍历找到相邻三个数加起来跟target绝对值差最小的,但这三个数不一定大小上相邻

  • 解法1(暴力):直接三重循环做
    • 要注意如果target为0,初始值不能设为-target
    • 初始化值选择前三个数是很不错的,随机任何一个数都可能跟target冲突
    • 最后一个样例会超时
  • 解法2(T48% S92%):首先排序,对第一个数遍历,第二三个数可以用双指针来做
    • ✨双指针不一定要向折半查找那样,也可以一次只移一位,这样中间的所有数都会照顾到,复杂度也从平方→线性
    • 改进1: 如果=target,直接终止
    • 改进2: 如果下一个数跟这一次一样,可以通过while将这些重复的枚举都省略掉
class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        save = nums[0]+nums[1]+nums[2]
        nums.sort()
        i = 0
        while i < len(nums)-2:
            left, right = i+1, len(nums)-1
            while left < right:
                this = nums[i]+nums[left]+nums[right]
                # 改进1
                if this == target:
                    return this
                elif this > target:
                    # 改进2
                    while right-1 > left and nums[right-1]==nums[right]:
                        right -= 1
                    right -= 1
                else:
                    while left+1 < right and nums[left+1]==nums[left]:
                        left += 1
                    left += 1
                if abs(this - target) < abs(save - target):
                    save = this
            
            while i+1 < len(nums)-2 and nums[i+1]==nums[i]:
                i += 1
            i += 1
        
        return save

    def otherSolution(self, nums, target):
        # 解法1 暴力法
        save = -target if target!=0 else 10000
        for i in range(len(nums)-2):
            for j in range(i+1, len(nums)-1):
                for k in range(j+1, len(nums)):
                    this = nums[i]+nums[j]+nums[k]
                    if this == target:
                        return target
                    elif abs(this - target) < abs(save - target):
                        save = this
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

doubleZ0108

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

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

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

打赏作者

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

抵扣说明:

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

余额充值