三数之和需排序后用双指针降维求解:固定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 等隐式转换问题
- 若需返回唯一索引组合(而非数值),本解法不适用,需改用哈希表辅助











