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

在算法题中,"三数之和" 是经典的数组类题目,属于 "两数之和" 的进阶版本,同时涉及去重这一关键细节。本文会拆解这道题的解题思路,并给出完整的 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)(排序所需的栈空间,若不考虑结果存储)。
相关推荐
稚南城才子,乌衣巷风流33 分钟前
ST 表(Sparse Table)算法详解:原理、实现与应用
算法
hold?fish:palm39 分钟前
9 找到字符串中所有字母异位词
c++·算法·leetcode
Sw1zzle1 小时前
算法入门(六):贪心算法 - 基础入门(Leetcode 121/455/860/376/738)
算法·leetcode·贪心算法
青山木1 小时前
Hot 100 --- 岛屿数量
java·数据结构·算法·leetcode·深度优先·广度优先
不会就选b1 小时前
算法日常・每日刷题--<归并排序>1
数据结构·算法
危桥带雨2 小时前
排序算法(快排、归并、计数、基数排序)
数据结构·算法·排序算法
啦啦啦啦啦zzzz2 小时前
算法:回溯算法
c++·算法·leetcode
会飞的小新2 小时前
C 标准库之 <fenv.h> 详解与深度解析
c语言·开发语言·microsoft
IT探索2 小时前
Linux 查找文件指令总结
linux·算法