675 字
3 分钟
三数之和
2025-08-22
无标签

题目描述#

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

**注意:**答案中不可以包含重复的三元组。

解题思路#

  1. 排序预处理
    • 将数组升序排序,便于双指针操作
    • 时间复杂度 O(n log n)
  2. 固定指针遍历
    • 外层循环固定第一个数 nums[i]
    • 内层使用双指针寻找另外两数
  3. 双指针搜索
    • 左指针 left = i + 1
    • 右指针 right = n - 1
  4. 和值判断
    • 三数和 > 0:右指针左移
    • 三数和 < 0:左指针右移
    • 三数和 = 0:记录结果并移动双指针
  5. 去重处理
    • 跳过重复的 nums[i]
    • 双指针移动时跳过相同值

关键洞察#

  1. 排序必要性
    • 排序后双指针能高效搜索目标值
    • 避免 O(n³) 的暴力解法
  2. 双指针优势
    • 将两数之和优化为 O(n) 操作
    • 总体复杂度降至 O(n²)
  3. 去重策略
    • 固定指针和前值比较避免重复
    • 双指针跳过相同元素防止重复组合
  4. 剪枝优化
    • nums[i] > 0 时提前终止
    • 最小三数和 > 0 时结束搜索

复杂度分析#

指标说明
时间复杂度O(n²):排序 O(n log n) + 双指针 O(n²)
空间复杂度O(1) 或 O(n):取决于排序实现
最优情况O(n²):无法低于平方复杂度

代码实现#

/**
* @param {number[]} nums
* @return {number[][]}
*/
var threeSum = function (nums) {
const result = [];
nums.sort((a, b) => a - b);
for (let i = 0; i < nums.length - 2; i++) {
if (i > 0 && nums[i] === nums[i - 1]) continue;
if (nums[i] > 0) break; // No need to continue if the smallest is > 0
let l = i + 1, r = nums.length - 1;
while (l < r) {
const sum = nums[i] + nums[l] + nums[r];
if (sum === 0) {
result.push([nums[i], nums[l], nums[r]]);
while (l < r && nums[l] === nums[l + 1]) l++;
while (l < r && nums[r] === nums[r - 1]) r--;
l++;
r--;
} else if (sum < 0) {
l++;
} else {
r--;
}
}
}
return result;
};

实际应用场景#

  1. 金融分析:找出投资组合中三只股票收益和为零的组合
  2. 化学计算:寻找三种化学物质PH值之和为中性的组合
  3. 游戏设计:匹配三件装备属性之和为特定值的组合`
  4. 数据挖掘:在用户行为数据中找出三种关联行为`

相似题目#

三数之和
https://website-truelovings-projects.vercel.app/posts/algorithms/三数之和/
作者
欢迎来到StarSky的网站!
发布于
2025-08-22
许可协议
CC BY-NC-SA 4.0