leetcode 三数之和

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        sort(nums.begin(), nums.end()); // 先排序
        vector<vector<int>> res;
        
        for (int i = 0; i < nums.size(); i++) {
            // 跳过重复元素
            if (i > 0 && nums[i] == nums[i - 1]) continue;
            
            // 双指针,目标是找到 nums[l] + nums[r] = -nums[i]
            int l = i + 1, r = nums.size() - 1;
            int target = -nums[i];
            
            while (l < r) {
                int sum = nums[l] + nums[r];
                if (sum == target) {
                    res.push_back({nums[i], nums[l], nums[r]});
                    l++;
                    r--;
                    // 跳过重复元素
                    while (l < r && nums[l] == nums[l - 1]) l++;
                    while (l < r && nums[r] == nums[r + 1]) r--;
                } else if (sum < target) {
                    l++;
                } else {
                    r--;
                }
            }
        }
        
        return res;
    }
};

核心思路:降维打击

三数之和 → 两数之和

text

复制代码
a + b + c = 0
     ↓ 固定 a
b + c = -a  ← 变成两数之和!

三个步骤

1. 排序

cpp

复制代码
sort(nums.begin(), nums.end());
// [-1,0,1,2,-1,-4] → [-4,-1,-1,0,1,2]

为了能用双指针,方便去重。

2. 固定第一个数 a

cpp

复制代码
for (int i = 0; i < nums.size(); i++) {
    if (i > 0 && nums[i] == nums[i - 1]) continue; // 跳过重复
    int target = -nums[i];  // b + c = target
    // 用双指针找 b 和 c
}

3. 双指针找 bc

cpp

复制代码
int l = i + 1, r = nums.size() - 1;
while (l < r) {
    int sum = nums[l] + nums[r];
    if (sum == target) {
        res.push_back({nums[i], nums[l], nums[r]});
        l++; r--;
        // 跳过重复
        while (l < r && nums[l] == nums[l-1]) l++;
        while (l < r && nums[r] == nums[r+1]) r--;
    } else if (sum < target) {
        l++;  // 和太小,左指针右移(变大)
    } else {
        r--;  // 和太大,右指针左移(变小)
    }
}

双指针移动逻辑

text

复制代码
[-4, -1, -1, 0, 1, 2]
  ↑    ↑           ↑
  i    l           r
  a    b           c

sum = b + c
- sum < target → l++ (让和变大)
- sum > target → r-- (让和变小)  
- sum == target → 找到答案,l++, r-- 继续找

为什么不会遗漏?

因为数组已排序 ,双指针可以保证遍历所有可能的 (l, r) 组合,只是跳过了不可能的组合。

text

复制代码
所有组合:O(n²)
    ↓ 双指针剪枝
有效组合:O(n)
相关推荐
政企项目老覃2 小时前
大模型幻觉治理与自动评测:金融风控场景的落地实践
人工智能·算法·机器学习
淡海水2 小时前
08-03-不可变-ImmutableDictionary-TKey-TValue-与ImmutableHashSet-T-持久化哈希树
数据结构·算法·c#·哈希算法·dictionary·immutable
hansang_IR2 小时前
【题解】[APIO2023] 赛博乐园 / cyberland
c++·算法·图论
洛阳纸贵3 小时前
MATLAB-matlab基础知识
学习·算法·matlab
落羽的落羽3 小时前
【AI】快速理解AI应用的相关名词概念
linux·c++·人工智能·python·计算机网络·算法
Nil2083 小时前
leetcode 17电话号码的字母组合
算法·leetcode·职场和发展
203号居民5 小时前
LeetCode hot 100 — 25. K 个一组翻转链表
算法·leetcode·链表
ocean21035 小时前
2025-2026年AI算法与模型研发面试高频知识点洞察
人工智能·算法·面试
Nil2085 小时前
leetcode 78子集
数据结构·算法·leetcode