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)
相关推荐
小小龙学IT2 小时前
C++ std::vector 底层实现深度解析:内存布局、扩容策略、移动语义与迭代器失效
开发语言·c++·算法
eBest数字化转型方案2 小时前
从工程视角拆解冰柜资产管理:拍照识别 pipeline、纯净度算法与 IoT 选型踩坑
人工智能·物联网·算法
Interview Aid1122 小时前
Roblox OA 面经|小游戏+编程双修,Coding 两题满分通过
算法
闲研随记3 小时前
【文献阅读 ICLR 2026】RL算法:Co-Rewarding
算法
青山木3 小时前
Hot 100 --- 最小栈
java·数据结构·算法·leetcode
疯狂打码的少年3 小时前
【数据结构】栈的应用:表达式求值(后缀表达式)
java·数据结构·笔记·算法
HiDev_3 小时前
【非标自动化】plc执行顺序问题、扫描周期问题
深度学习·算法·机器学习
高洁013 小时前
工信部教考中心证书-人工智能系列本系列
人工智能·python·深度学习·算法
陈王卜4 小时前
Reduce 算子优化笔记
算法