note_leetcode_三数相加

来源:

https://zhuanlan.zhihu.com/p/114938369

题目:

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组

源码:

class Solution(object):
    def threeSum(self, nums):
        nums.sort()  # 排序
        res = []
        for i in range(len(nums)):  # 遍历每一个数
            if i == 0 or nums[i] > nums[i - 1]:  # 确定不重复的数字(开头)
                l = i + 1
                r = len(nums) - 1
                while l < r:  # 左边的位置 必须小于 右边的位置
                    s = nums[i] + nums[l] + nums[r]  # 三个数的和
                    if s == 0:
                        res.append([nums[i], nums[l], nums[r]])
                        # 再找下一组解
                        l += 1
                        r -= 1
                        # 左边向右移动到不重复数为止
                        while l < r and nums[l] == nums[l - 1]: l += 1
                        # 右边向左边移动不重复数为止
                        while r > l and nums[r] == nums[r + 1]: r -= 1
                    elif s > 0:
                        r -= 1
                    else:
                        l += 1

            # else:  
            #     break
        return res


# test case
# [-4,-3,-4,2,2,1,2],  [-4,-4,2,2,1,3],  [-4, -4, ]
# [-4,-4,2,2,-5,4,1,1,3],   [0,-4,-1,-4,-2,-3,2]

res = Solution().threeSum([0,-4,-1,-4,-2,-3,2])
print(res)

思路分析:

  • 思路1:利用排列组合,列出子序列的所有情况
  • 思路2:见流程图,不是严格意义上的flow chart

在这里插入图片描述

Q&A:

  • 为啥要确定不重复数字
    答:假设输入 [-4,-4,2,2,-5,4,1,1,3],在遍历整个列表时候,第一个数和第二个数相同,那么第二个数也同样做第一个数相同的寻找操作

  • 会不会遗漏一些中间元素
    答:每次循环的开始,都进行l = i + 1和r = len(nums) - 1的操作

  • i == 0 or nums[i] > nums[i - 1] 中的i==0 能不能去掉?
    答:Nope, 该if 语句的作用是跳过重复元素,但第一个元素比较特殊,python中nums[-1]为最后一个元素, 也就是, 第一个元素和最后一个元素作比较,和我们想要跳过下一个重复元素的初衷相悖,如果测试用例是[0,0,0],去掉i=0就报错…这句话还有一个亮点就是,or 短路运算符 只要一个判断正确,整个语句就正确

  • 在 代码最后加入else: break 后,无法处理一种情况,测试用例[0,-4,-1,-4,-2,-3,2],本例中,第一个元素无法找到答案,在遍历第二个元素后就会直接break

  • 比较Gorgeous的地方,是 定位答案的措施,利用后一个元素和最后一个元素

  • 能不能刚开始就寻找好l和r的位置?
    答:可以是可以,但仍然需要考虑i=0的特殊位置

安利流程图,思维导图在线操作:

https://www.processon.com/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值