破解三数之和:双指针高效解法

在算法题中,"三数之和" 是经典的数组类题目,属于 "两数之和" 的进阶版本,同时涉及去重这一关键细节。本文会拆解这道题的解题思路,并给出完整的 C++ 实现代码。

一、题目分析

给定整数数组nums,找出所有满足nums[i]+nums[j]+nums[k]=0i/j/k互不相等的三元组,结果不能包含重复的三元组

  • 核心难点:
    1. 如何高效枚举三元组(避免暴力 O (n³) 的时间复杂度);
    2. 如何去除重复的三元组(例如[-1,0,1][0,-1,1]属于重复结果)。

二、解题思路:排序 + 双指针

1. 预处理:排序数组

先对数组排序,好处有两个:

  • 方便后续用双指针缩小查找范围;
  • 便于去重(相同元素会相邻,可跳过重复项)。

2. 枚举 + 双指针查找

固定一个数nums[i],然后在i右侧的区间内,用左指针left=i+1、右指针right=n-1 寻找满足nums[left]+nums[right] = -nums[i]的组合:

  • nums[left]+nums[right] < -nums[i]:左指针右移(增大和);
  • nums[left]+nums[right] > -nums[i]:右指针左移(减小和);
  • 若相等:记录该三元组,同时跳过左右指针的重复元素(避免重复结果)。

3. 去重细节

  • 固定nums[i]时,若nums[i] == nums[i-1],直接跳过(避免重复枚举同一个基准数);
  • 找到有效三元组后,左指针需跳过所有与nums[left]相等的元素,右指针同理。

三、完整 C++ 代码实现

cpp

复制代码
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        vector<vector<int>> result;
        sort(nums.begin(), nums.end()); // 排序
        int n = nums.size();
        
        for (int i = 0; i < n; ++i) {
            // 基准数去重
            if (i > 0 && nums[i] == nums[i-1]) {
                continue;
            }
            int target = -nums[i];
            int left = i + 1;
            int right = n - 1;
            
            while (left < right) {
                int sum = nums[left] + nums[right];
                if (sum == target) {
                    // 记录有效三元组
                    result.push_back({nums[i], nums[left], nums[right]});
                    // 左指针去重
                    while (left < right && nums[left] == nums[left+1]) {
                        left++;
                    }
                    // 右指针去重
                    while (left < right && nums[right] == nums[right-1]) {
                        right--;
                    }
                    // 移动指针继续查找
                    left++;
                    right--;
                } else if (sum < target) {
                    left++;
                } else {
                    right--;
                }
            }
        }
        return result;
    }
};

四、复杂度分析

  • 时间复杂度:O (n²)(排序 O (nlogn) + 枚举基准数 O (n) * 双指针遍历 O (n));
  • 空间复杂度:O (logn)(排序所需的栈空间,若不考虑结果存储)。
相关推荐
先吃饱再说10 小时前
判断回文字符串,从一行代码到双指针优化
算法
见过夏天11 小时前
C++ 基础入门完全指南
c++
黄敬峰13 小时前
深入理解算法核心:从递归思想、数组扁平化到快速排序
算法
得物技术14 小时前
从狂野代码到按目标生产:得物推荐 AI Harness 的工程化实践|AICon 演讲整理
人工智能·算法·架构
AI小老六18 小时前
SkillOpt 架构拆解:把 Skill 文本当参数,用执行轨迹训练 Agent
后端·算法·ai编程
胡萝卜术18 小时前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
Asize19 小时前
初识DFS 与 BFS:递归、队列与图遍历
算法
努力的小雨1 天前
我用 QClaw 做了个 Web3 陪学助手,专治 Java 程序员的“概念劝退”
经验分享·ai智能
罗西的思考1 天前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习