675 字
3 分钟
三数之和
.jpg)
题目描述
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
**注意:**答案中不可以包含重复的三元组。
解题思路
- 排序预处理:
- 将数组升序排序,便于双指针操作
- 时间复杂度 O(n log n)
- 固定指针遍历:
- 外层循环固定第一个数 nums[i]
- 内层使用双指针寻找另外两数
- 双指针搜索:
- 左指针 left = i + 1
- 右指针 right = n - 1
- 和值判断:
- 三数和 > 0:右指针左移
- 三数和 < 0:左指针右移
- 三数和 = 0:记录结果并移动双指针
- 去重处理:
- 跳过重复的 nums[i]
- 双指针移动时跳过相同值
关键洞察
- 排序必要性:
- 排序后双指针能高效搜索目标值
- 避免 O(n³) 的暴力解法
- 双指针优势:
- 将两数之和优化为 O(n) 操作
- 总体复杂度降至 O(n²)
- 去重策略:
- 固定指针和前值比较避免重复
- 双指针跳过相同元素防止重复组合
- 剪枝优化:
- 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;};
实际应用场景
- 金融分析:找出投资组合中三只股票收益和为零的组合
- 化学计算:寻找三种化学物质PH值之和为中性的组合
- 游戏设计:匹配三件装备属性之和为特定值的组合`
- 数据挖掘:在用户行为数据中找出三种关联行为`