三数之和

GitHub跳转原题关系图返回列表

排序后固定第一个数,剩余区间用双指针,跳过相同值去重,O(n²)。

OJ: leetcodecn

题目 ID: 3sum

难度:普及+/提高

标签:双指针排序数组cpppython

日期: 2026-07-28 22:03

题意

找出数组中所有和为 0 且不重复的三元组。

思路

三重循环枚举 O(n³) 会超时。排序后固定第一个数,在剩余区间中用双指针寻找两数之和等于 -nums[i]

去重是关键:排序后,每层循环(第一个数、左指针、右指针)在移动时跳过相同值,避免重复三元组。

代码

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 */
// main.cpp:排序 + 固定第一个数 + 双指针,O(n²)。
#include <bits/stdc++.h>
using namespace std;

class Solution {
public:
    vector<vector<int>> threeSum(vector<int> &nums) {
        sort(nums.begin(), nums.end());
        vector<vector<int>> ans;
        int n = nums.size();
        for (int i = 0; i < n - 2; i++) {
            if (i && nums[i] == nums[i - 1])
                continue;
            int l = i + 1, r = n - 1;
            while (l < r) {
                int sum = nums[i] + nums[l] + nums[r];
                if (sum == 0) {
                    ans.push_back({nums[i], nums[l], nums[r]});
                    while (l < r && nums[l] == nums[l + 1])
                        l++;
                    while (l < r && nums[r] == nums[r - 1])
                        r--;
                    l++;
                    r--;
                } else if (sum < 0)
                    l++;
                else
                    r--;
            }
        }
        return ans;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<int> a(n);
    for (int &x : a)
        cin >> x;
    auto ans = Solution().threeSum(a);
    for (auto &v : ans) {
        for (int x : v)
            cout << x << ' ';
        cout << '\n';
    }
    return 0;
}
python
#!/usr/bin/env python3
from typing import List


class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        n = len(nums)
        ans = []
        for i in range(n - 2):
            if i and nums[i] == nums[i - 1]:
                continue
            l, r = i + 1, n - 1
            while l < r:
                s = nums[i] + nums[l] + nums[r]
                if s == 0:
                    ans.append([nums[i], nums[l], nums[r]])
                    while l < r and nums[l] == nums[l + 1]:
                        l += 1
                    while l < r and nums[r] == nums[r - 1]:
                        r -= 1
                    l += 1
                    r -= 1
                elif s < 0:
                    l += 1
                else:
                    r -= 1
        return ans


def main() -> None:
    n = int(input())
    nums = list(map(int, input().split()))
    ans = Solution().threeSum(nums)
    for v in ans:
        print(*v)


if __name__ == "__main__":
    main()

复杂度

  • 时间复杂度:O(n²),排序 O(n log n),双指针 O(n²)。
  • 空间复杂度:O(1),不计答案空间。

总结

三数之和是两数之和的推广:固定一个数转化为两数之和问题,再套用双指针。排序辅助去重的做法比用哈希集合去重更干净。