题目
给你一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 _a + b + c = _0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4]
,
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
方案一
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 双指针
if len(nums) < 2:
return []
nums.sort()
i, j, k = 1, len(nums) - 1, 0
res = []
# 固定一个指针 k
while k < len(nums):
if nums[k] > 0: # 最小的数大于 0
break
# i, j 从两端往中间步进
while i < j:
count = nums[k] + nums[i] + nums[j]
if count == 0:
res.append([nums[k], nums[i], nums[j]])
i += 1
j -= 1
while i < j:
if nums[i] == nums[i - 1]: # 连续相同
i += 1
else:
break
while i < j:
if nums[j] == nums[j + 1]: # 连续相同
j -= 1
else:
break
elif count < 0:
i += 1
while i < j:
if nums[i] == nums[i - 1]: # 连续相同
i += 1
else:
break
else:
j -= 1
while i < j:
if nums[j] == nums[j + 1]: # 连续相同
j -= 1
else:
break
k += 1
while k < len(nums):
if nums[k] == nums[k - 1]: # 连续相同
k += 1
else:
break
i = k + 1
j = len(nums) - 1
return res
优化代码结构
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
# 双指针
if len(nums) < 2:
return []
nums.sort()
i, j, k = 1, len(nums) - 1, 0
res = []
# 固定一个指针 k
while k < len(nums):
if nums[k] > 0: # 最小的数大于 0
break
while i < j:
count = nums[k] + nums[i] + nums[j]
if count == 0:
res.append([nums[k], nums[i], nums[j]])
i += 1
j -= 1
# 跳过相同元素
while i < j and nums[i] == nums[i - 1]: i += 1
while i < j and nums[j] == nums[j + 1]: j -= 1
elif count < 0:
i += 1
while i < j and nums[i] == nums[i - 1]: i += 1
else:
j -= 1
while i < j and nums[j] == nums[j + 1]: j -= 1
k += 1
while k < len(nums) - 1 and nums[k] == nums[k - 1]: k += 1
# 重置 i, j 指针
i = k + 1
j = len(nums) - 1
return res
- 时间复杂度
方案二(两数之和升级版)
两数之和题目链接: https://leetcode-cn.com/explore/orignial/card/all-about-lockup-table/238/lookup-table-related-sum-questions/991/
class Solution:
def twoSum(self, nums, target, l, r):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
n = len(nums[l: r+1])
if n < 2:
return set()
start = nums[l - 1]
dict1 = dict()
ret = set()
for i in range(l, r+1):
other = target - nums[i]
if other in dict1:
ret.add((start, other, nums[i]))
dict1[nums[i]] = i
return ret
def threeSum(self, nums):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
n = len(nums)
if n < 3:
return []
nums.sort()
ret = set()
for i in range(n):
# nums[i] 为正数,表示后面不可能有两数之后为负
if nums[i] > 0:
break
if (i >= 1 and nums[i] == nums[i-1]):
continue
ll = self.twoSum(nums, -nums[i], i+1, n-1)
if ll == set():
continue
ret = ret | ll
return list(ret)