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

在算法题中,"三数之和" 是经典的数组类题目,属于 "两数之和" 的进阶版本,同时涉及去重这一关键细节。本文会拆解这道题的解题思路,并给出完整的 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)(排序所需的栈空间,若不考虑结果存储)。
相关推荐
Hcoco_me13 分钟前
大模型面试题75:讲解一下GRPO的数据回放
人工智能·深度学习·算法·机器学习·vllm
Xの哲學16 分钟前
Linux设备驱动模型深度解剖: 从设计哲学到实战演练
linux·服务器·网络·算法·边缘计算
明洞日记31 分钟前
【CUDA手册002】CUDA 基础执行模型:写出第一个正确的 Kernel
c++·图像处理·算法·ai·图形渲染·gpu·cuda
mikelv0135 分钟前
实现返回树状结构小记
java·数据结构
企业对冲系统官1 小时前
基差风险管理系统集成说明与接口规范
大数据·运维·python·算法·区块链·github
程序员-King.1 小时前
day134—快慢指针—环形链表(LeetCode-141)
算法·leetcode·链表·快慢指针
Swift社区1 小时前
LeetCode 376 摆动序列
算法·leetcode·职场和发展
oioihoii1 小时前
程序员如何系统入门Vibe Coding?
c++
高洁011 小时前
AIGC技术与进展(1)
深度学习·算法·机器学习·transformer·知识图谱
C+++Python1 小时前
C++类型判断
开发语言·c++