news 2026/5/1 10:00:14

三数之和问题的高效解法:双指针技巧详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
三数之和问题的高效解法:双指针技巧详解

问题描述

三数之和(3Sum)是一个经典的算法问题:给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a, b, c,使得 a + b + c = 0?找出所有满足条件且不重复的三元组。

解决方案思路

1. 核心思路

这个问题最直接的暴力解法需要 O(n³) 的时间复杂度,显然是不可取的。本文介绍的解决方案采用了以下优化策略:

  1. 排序:首先将数组排序,这样可以将时间复杂度降低到 O(n²)

  2. 固定一个数:遍历数组,每次固定一个数 nums[i]

  3. 双指针查找:使用左右指针在固定数右侧的区间内查找另外两个数

2. 算法步骤

cpp

vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> res; sort(nums.begin(), nums.end()); // 1. 排序 int n = nums.size(); for (int i = 0; i < n; ++i) { // 2. 提前终止:如果当前数大于0,三数之和不可能为0 if (nums[i] > 0) break; // 3. 去重:跳过重复的固定数 if (i > 0 && nums[i] == nums[i-1]) continue; // 4. 双指针查找 int left = i + 1; int right = n - 1; while (left < right) { int sum = nums[i] + nums[left] + nums[right]; if (sum == 0) { // 找到有效三元组 res.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 < 0) { left++; // 和太小,左指针右移 } else { right--; // 和太大,右指针左移 } } } return res; }

关键点解析

1. 排序的重要性

排序是此算法的基础,它带来了三个好处:

  • 可以使用双指针技巧将查找两个数的时间复杂度从 O(n²) 降为 O(n)

  • 便于去重操作

  • 可以提前终止搜索(当固定数大于0时)

2. 去重处理

去重是解决三数之和问题的关键,代码中实现了两种去重:

  1. 固定数的去重

cpp

if (i > 0 && nums[i] == nums[i-1]) continue;

跳过相同的固定数,避免重复的三元组。

  1. 左右指针的去重

cpp

while (left < right && nums[left] == nums[left+1]) left++; while (left < right && nums[right] == nums[right-1]) right--;

在找到有效三元组后,跳过左右指针指向的重复值。

3. 双指针的移动逻辑

  • 当三数之和等于0时,记录结果并同时移动左右指针

  • 当三数之和小于0时,说明需要更大的数,左指针右移

  • 当三数之和大于0时,说明需要更小的数,右指针左移

复杂度分析

时间复杂度

  • 排序:O(n log n)

  • 外层循环:O(n)

  • 内层双指针循环:O(n)

  • 总体:O(n²)

空间复杂度

  • 除了输出结果外,只使用了常量级额外空间:O(1)

  • 如果考虑存储结果的空间:O(k),其中 k 是结果数量

示例演示

以数组[-1, 0, 1, 2, -1, -4]为例:

  1. 排序后:[-4, -1, -1, 0, 1, 2]

  2. 固定 -4,在 [-1, -1, 0, 1, 2] 中查找两数之和为4 → 无解

  3. 固定第二个 -1(跳过第一个 -1 的重复),在 [-1, 0, 1, 2] 中查找两数之和为1

    • 找到 [-1, 0, 1] 和 [-1, -1, 2]

边界情况考虑

  1. 数组长度小于3:直接返回空结果

  2. 所有数都为正或都为负:不可能有三数之和为0

  3. 大量重复元素:去重逻辑确保结果不重复

  4. 溢出问题:虽然题目未明确,但实际应用中需要考虑整数溢出

扩展与变种

  1. 最接近的三数之和:找到和与目标最接近的三个数

  2. 四数之和:类似的思路可以扩展到四数之和问题

  3. 三数之和为任意目标值:将0改为任意目标值

总结

三数之和问题展示了如何通过排序和双指针技巧将 O(n³) 的暴力解法优化到 O(n²)。这个解决方案的关键在于:

  1. 排序预处理

  2. 固定一个数转化为两数之和问题

  3. 双指针高效查找

  4. 仔细处理去重逻辑

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 20:43:14

利用Fabry-Pérot标准具检测钠D线

摘要Fabry-Prot标准具广泛用于激光谐振腔和光谱仪中进行波长的选择。 通常&#xff0c;由两个高反射&#xff08;HR&#xff09;涂层表面组成&#xff0c;其间具有空气或玻璃。 在该示例中&#xff0c;利用VirtualLab Fusion设置了具有二氧化硅间隔标准具的光学测量系统&#x…

作者头像 李华
网站建设 2026/4/30 11:01:03

三层立体车库PLC(S7-1200)报告与仿真分享

三层立体车库plc s7-1200 报告和仿真都有。 确保正常运行&#xff0c;虚拟产品&#xff0c;一经售出拒不退款 有主电路图&#xff0c;没有PLC接线图 1、设置启动、停止按钮&#xff0c;且设置指示灯显示车库的开关状态&#xff1b; 2、7个车位的车俩可以自由存取&#xff0c;且…

作者头像 李华
网站建设 2026/5/1 7:17:22

Wan2.2-T2V-A14B生成港珠澳大桥建设奇迹回顾视频

Wan2.2-T2V-A14B生成港珠澳大桥建设奇迹回顾视频 你有没有想过&#xff0c;一段从未被真实记录过的海底隧道沉管对接过程&#xff0c;居然能“复活”在屏幕上&#xff1f;&#x1f30a; 港珠澳大桥&#xff0c;这座横跨伶仃洋的超级工程&#xff0c;许多关键施工环节——尤其是…

作者头像 李华
网站建设 2026/5/1 7:12:46

AI草图转代码终极指南:从涂鸦到网页的魔法之旅 [特殊字符]

AI草图转代码终极指南&#xff1a;从涂鸦到网页的魔法之旅 &#x1f3a8; 【免费下载链接】ailab Experience, Learn and Code the latest breakthrough innovations with Microsoft AI 项目地址: https://gitcode.com/gh_mirrors/ai/ailab 你是否曾幻想过&#xff0c;只…

作者头像 李华
网站建设 2026/4/30 9:39:44

芯片可靠性守护神:动态电压应力测试(DVS)完全解析

在芯片制程不断微缩的今天&#xff0c;5纳米、3纳米先进工艺已成为常态&#xff0c;芯片内部集成了上百亿个晶体管。这些微小结构在复杂的工作环境下&#xff0c;如同行走在钢丝上&#xff0c;任何微小的缺陷都可能导致整个芯片失效。而动态电压应力测试&#xff08;DVS&#x…

作者头像 李华
网站建设 2026/5/1 8:37:53

Blender骨骼动画重定向:5分钟掌握高效动画转移技巧

Blender骨骼动画重定向&#xff1a;5分钟掌握高效动画转移技巧 【免费下载链接】blender_BoneAnimCopy 用于在blender中桥接骨骼动画的插件 项目地址: https://gitcode.com/gh_mirrors/bl/blender_BoneAnimCopy 还在为不同角色间的动画适配而烦恼吗&#xff1f;Bone Ani…

作者头像 李华