三数之和需排序后用双指针降维求解:固定nums[i],左右指针找另两数使和为0;关键在i层及指针内双重去重,避免重复三元组。

三数之和(3Sum)是经典的数组双指针问题,核心在于去重 + 降维:先排序,再固定一个数,用左右指针找另外两数,使三者和为零。
排序 + 双指针:基础实现逻辑
暴力三层循环时间复杂度 O(n³),不可取。优化思路是:
- 对数组升序排序,便于跳过重复值、控制指针移动方向
- 外层遍历 i(0 到 n−3),固定 nums[i] 作为第一个数
- 内层设 left = i+1,right = n−1,计算 sum = nums[i] + nums[left] + nums[right]
- 若 sum == 0,记录结果;sum 0 则 right–
- 每次找到解后,left 和 right 都要跳过相邻重复值,避免重复三元组
关键去重处理:避免重复三元组
重复可能发生在两个层级:
- i 层去重:若 nums[i] == nums[i−1](i > 0),说明该轮已处理过相同首元素,直接 continue
- 双指针内去重:找到一组解后,left 向右跳过所有 nums[left] == nums[left+1],right 向左跳过所有 nums[right] == nums[right−1]
注意:i 层去重用的是 前一个索引 比较,而指针内去重是在 找到解之后 才执行,顺序不能颠倒。
立即学习“PHP免费学习笔记(深入)”;
php 实现示例(含注释)
(使用标准输入输出,兼容 PHP 7.4+)
function threeSum($nums) { $n = count($nums); if ($n sort($nums); // 升序排序 $result = []; for ($i = 0; $i < $n - 2; $i++) { // i 层去重 if ($i > 0 && $nums[$i] === $nums[$i - 1]) { continue; } $left = $i + 1; $right = $n - 1; while ($left < $right) { $sum = $nums[$i] + $nums[$left] + $nums[$right]; if ($sum === 0) { $result[] = [$nums[$i], $nums[$left], $nums[$right]]; // left 和 right 去重(必须在存入结果后) while ($left < $right && $nums[$left] === $nums[$left + 1]) $left++; while ($left < $right && $nums[$right] === $nums[$right - 1]) $right--; $left++; $right--; } elseif ($sum < 0) { $left++; } else { $right--; } } } return $result;
}
// 示例调用 // var_dump(threeSum([-1, 0, 1, 2, -1, -4])); // 输出:[[-1,-1,2],[-1,0,1]]
边界与性能提醒
- 空数组或元素少于 3 个时,直接返回空数组
- 排序时间复杂度 O(n log n),主循环 O(n²),整体为 O(n²)
- PHP 中注意用 === 严格比较,避免 -0 与 0 等隐式转换问题
- 若需返回唯一索引组合(而非数值),本解法不适用,需改用哈希表辅助