直接回答:先排序,然后固定第一个数 nums[i],在 i 之后的区间用左右双指针找两数之和等于 −nums[i]——这就是「排序 + 双指针」把 O(n³) 降到 O(n²)。排序后相同的数相邻,跳过重复元素即可保证三元组不重复。
展开解析:去重是这题的主要考点,有三处:1)外层枚举 i 时跳过与前一个相同的值;2)内层找到一组解后左右指针各自跳过连续重复值;3)第二层不必用哈希集合去重,排序天然解决了组合顺序问题(i < left < right)。另一个要点是剪枝:nums[i] > 0 时可以直接结束,因为后面全是正数。复杂度 O(n²) 时间、O(log n)~O(n) 排序栈空间。追问方向:与两数之和的哈希解法对比(为什么三数之和不优先用哈希——去重变复杂)、kSum 的通用递归框架(降到两数之和为止)、三数之和最接近目标值的变体。
示例:
def three_sum(nums):
nums.sort()
res, n = [], len(nums)
for i in range(n - 2):
if i > 0 and nums[i] == nums[i - 1]:
continue
if nums[i] > 0:
break
lo, hi = i + 1, n - 1
while lo < hi:
s = nums[i] + nums[lo] + nums[hi]
if s < 0: lo += 1
elif s > 0: hi -= 1
else:
res.append([nums[i], nums[lo], nums[hi]])
while lo < hi and nums[lo] == nums[lo + 1]: lo += 1
while lo < hi and nums[hi] == nums[hi - 1]: hi -= 1
lo, hi = lo + 1, hi - 1
return res