直接回答:先排序,然后固定第一个数 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