双指针法解三数之和需先排序,外层遍历i并跳过重复,内层用left/right收缩搜索空间,sum为0时双向跳重并同时移动指针,边界须防下溢与越界。

用双指针法解决三数之和(C++)
直接暴力三层循环在 nums.size() 较大时会超时(O(n³)),实际项目中必须优化。标准解法是先排序 + 双指针,时间复杂度降到 O(n²),空间 O(1)(不计结果存储)。
关键前提:数组必须排序,否则无法通过移动左右指针来系统性收缩搜索空间。
常见错误现象:[-1,0,1,2,-1,-4] 输出重复三元组如 [-1,0,1] 出现两次;或漏掉某组解(比如跳过连续相同元素时边界错位)。
- 对
nums排序:sort(nums.begin(), nums.end()) - 外层遍历
i从0到nums.size()-3,每次固定nums[i]为第一个数 - 跳过重复值避免重复解:
if (i > 0 && nums[i] == nums[i-1]) continue; - 内层设
left = i+1、right = nums.size()-1,计算sum = nums[i] + nums[left] + nums[right] - 若
sum == 0,存入结果,并同时跳过left和right方向的重复值 - 若
sum ,<code>left++;若sum > 0,right--
为什么不能用哈希表暴力替代双指针
有人想用两层循环 + unordered_set 查第三个数,看似 O(n²),但实际有坑:
- 无法自然去重:
[-1,-1,2]中两个-1是不同下标,但哈希表只存值,容易误判可用性 - 需要额外记录频次(如用
unordered_map<int int></int>),逻辑变复杂且易错 - 当存在
[0,0,0]时,需确保数组中真有至少三个0,而哈希频次更新与检查顺序极易出错 - 排序+双指针天然支持跳过重复值,哈希方案得额外做去重后处理,反而更慢
边界处理最容易错的三个地方
实测中 70% 的 WA(Wrong Answer)来自以下细节:
-
i的上界写成nums.size()-2—— 错!应是nums.size()-3,因为还要留两个位置给left和right - 跳过
nums[i]重复时用了nums[i] == nums[i+1]—— 错!应该和前一个比(i-1),否则会跳过合法的首元素 - 找到一组解后只移动
left或只移动right—— 错!必须两者都动,否则可能漏解或死循环(比如[-2,0,1,1,2]中固定-2后,[0,2]和[1,1]都满足,需分别跳过
完整可跑的最小代码片段(含注释)
vector<vector>> threeSum(vector<int>& nums) {
vector<vector>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i 0 && nums[i] == nums[i-1]) continue; // 去重第一维
int left = i + 1, right = nums.size() - 1;
while (left <p>注意:<code>(int)nums.size() - 2</code> 是为了防止 <code>size_type</code> 无符号整数下溢(当 <code>nums</code> 为空时);所有跳过重复的 while 循环都带 <code>left 安全检查。</code></p>
<p>真正难的不是写出来,而是第一次写时能想到所有重复场景和边界条件——多拿 <code>[-1,-1,0,0,1,1,2]</code> 这类数据手动走一遍指针变化,比看十遍代码管用。</p></vector></int></vector>C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











