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. 双指针找 b 和 c

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)
相关推荐
自信1504130575913 分钟前
重生之从0开始学习c++之——vector-中篇
c++·学习·算法
文丑颜不良啊15 分钟前
LeetCode2501~2520题目解析
java·leetcode
GoAI11 小时前
DeepSeek Harness Memory (一)主流记忆插件总结
后端·算法·面试
Pniubi12 小时前
力扣54.螺旋矩阵
算法·leetcode·矩阵
choumou_M14 小时前
算法_1:由浅入深学习快速排序QuickSort
学习·算法·排序算法
Coder_Shenshen15 小时前
罗克韦尔ACD工程归档离线变量树解析
算法·c#
心仪久了会沦陷17 小时前
C语言数据结构入门——树与二叉树详解:概念、堆实现与链式遍历
c语言·数据结构·算法
小此方17 小时前
[算法实战论:动态规划]背包问题概念,01不满背包问题,01满背包问题,背包问题的滚动数组空间优化
算法·动态规划
悠仁さん18 小时前
【C++】哈希表
c++·算法·散列表