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)
相关推荐
朔北之忘 Clancy1 分钟前
2024 CSP-J 第二轮真题解析
c++·算法·青少年编程·noip·csp·信奥赛·noi
小七在进步34 分钟前
类和对象(五)
java·开发语言·算法
wzdark39 分钟前
算法与数据结构教学的可视化新模式探索4
数据结构
就叫年华吧丶43 分钟前
长文档点目录定位总是不准?一个 content-visibility + 平滑滚动引发的连环坑(Vue3 实战)
前端·javascript·算法·vue
FPGA信号处理1 小时前
【信号检测与估计】第四节课:非高斯噪声下的 BLUE、极大似然与 EM 算法
人工智能·算法·机器学习
.道阻且长.1 小时前
C++ 11:可变参数模板
前端·c++·算法
hzxpaipai1 小时前
企业官网后台怎么设计?从产品分类、参数到资料下载的数据结构
数据结构
Doubbbbbbble云4 小时前
基于贪心算法的区间覆盖问题求解策略4
算法·贪心算法
不会就选b10 小时前
算法日常・每日刷题--<贪心>25
数据结构·算法
Cccp.12313 小时前
【leetcode】(七)前缀树和贪心算法
数据结构·leetcode·贪心算法