Day2_三数之和

首先暴力解法不用说了,看了评论的双指针提示,尝试写了如下代码:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        result=[]
        for i in range(len(nums)):
            l=i+1
            r=len(nums)-1
            while(l<r):
                if(nums[i]+nums[l]+nums[r]<0 ):
                    l=l+1
                elif(nums[i]+nums[l]+nums[r]>0 ):
                    r=r-1
                elif((nums[i]+nums[l]+nums[r]==0 )):
                    result.append([nums[i],nums[l],nums[r]])
                    break
        return result

问题大的很,首先是边界判断,l!=r 和l<r 有点纠结,前者貌似也行,但是有点不符合左右指针的特点。第二break语句有点模糊,这里的break加入之后,万一在等于0之后,右边还有其他满足的情况呢?[-2,0,1,1,2]比如 第一遍遍历到-2 0 2时就结束了,但其实-2 1 1也满足没有找到所有情况。改进之后
在以上基础之上改进,然后超时了,淦!!!:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        result=[]
        for i in range(len(nums)):
            l=i+1
            r=len(nums)-1
            while(l<r):
                if(nums[i]+nums[l]+nums[r]<0 ):
                    l=l+1
                elif(nums[i]+nums[l]+nums[r]>0 ):
                    r=r-1
                elif((nums[i]+nums[l]+nums[r]==0 )):
                    result.append([nums[i],nums[l],nums[r]])
                    l=l+1
        final=[]
        for i in result:
            if i not in final:
                final.append(i)
        return final

直接上大佬代码吧:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        #
        #-4 -1 -1 0 1 2
        # i  l        r
        nums.sort()
        res=[]
        i=0
        for i in range(len(nums) - 2):#减2是因为左右指针占了两个位置
            if nums[i] > 0: break # 1. because of j > i > k.
            if i > 0 and nums[i] == nums[i - 1]: continue # 2. skip the same `nums[k]`.
            l, r = i + 1, len(nums) - 1
            while l != r: # 3. double pointer
                s = nums[i] + nums[l] + nums[r]
                if s < 0:
                    l += 1
                    while l != r and nums[l] == nums[l - 1]: #跳过重复的值nums[l] != nums的时候指针就不走了
                        l += 1
                elif s > 0:
                    r -= 1
                    while l != r and nums[r] == nums[r + 1]: 
                        r -= 1
                else:
                    res.append([nums[i], nums[l], nums[r]])
                    l += 1
                    r -= 1
                    while l != r and nums[l] == nums[l - 1]: 
                        l += 1
                    while l != r and nums[l] == nums[r + 1]: 
                        r -= 1
        return res

N数之和通用思路
解题思路
首先要熟悉求两数之和的写法,然后在 N > 2时,采用递归处理,一次减少1。
关键点是:

  1. 先对nums排序;
  2. 递归处理时的剪枝处理(参考注释)
    这种写法参考了国际站上的文章,我觉得是最好的一种解法了。

代码

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        if not nums: return []

        # 先排序,关键!
        nums.sort()     
        ans = set()
        N, target = 3, 0
        self._find_sum(nums, 0, N, target, [], ans)
        return list(ans)

    def _find_sum(self, nums, start, N, target, path, ans):
        # terminator
        if len(nums) < N or N < 2: return
        # process
        if N == 2:
            # 两数求和
            d = set()
            for j in range(start, len(nums)):
                if target - nums[j] in d:
                    ans.add(tuple(path + [target - nums[j], nums[j]]))
                else:
                    d.add(nums[j])
        else:
            for i in range(start, len(nums)):
                # 剪枝1: target比剩余数字能组成的最小值还要小 或 比能组成的最大值还要大,就可以停止循环了
                if target < nums[i] * N or target > nums[-1] * N: break
                # 剪枝2: 去重
                if i > start and nums[i] == nums[i - 1]: continue
                # drill down
                self._find_sum(nums, i + 1, N - 1, target - nums[i], path + [nums[i]], ans)
        return
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值