来源:
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的特殊位置