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

在算法题中,"三数之和" 是经典的数组类题目,属于 "两数之和" 的进阶版本,同时涉及去重这一关键细节。本文会拆解这道题的解题思路,并给出完整的 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)(排序所需的栈空间,若不考虑结果存储)。
相关推荐
zhonghaoxincekj5 分钟前
轴距可调式元器件双边无损成形钳
经验分享·科技·深度学习·学习·测试工具·创业创新·制造
灵动小溪7 分钟前
claude code工具PC安装部署
人工智能·算法
fan_music1 小时前
C语言如何实现C++的类
开发语言·c++
一个人旅程~1 小时前
如何永久关闭bitlocker并防止出现更新后被强制加密?
linux·windows·经验分享·电脑
Asa121381 小时前
Nature Microbiology|跨微生物界菌株水平传播推断的新算法TRACS
算法
_君莫笑1 小时前
Qt+Qml前后端分离上位机软件技术方案
c++·qt·用户界面·qml
叼烟扛炮1 小时前
C++ 知识点22 函数模板
开发语言·c++·算法·函数模版
Tisfy1 小时前
LeetCode 2553.分割数组中数字的数位:模拟(maybe+翻转)——java也O(1)
java·数学·算法·leetcode·题解·模拟·取模
平行侠1 小时前
33水库抽样 - 从未知大小的流中等概率采样
数据结构·算法
吴声子夜歌1 小时前
Java——Integer与二进制算法
java·算法