class Solution {
public:
vector<vector<int>> threeSum(vector<int>& num) {
vector<vector<int>> result;
int n = num.size();
if (n < 3) {
return result;
}
// 先对数组进行排序
sort(num.begin(), num.end());
for (int i = 0; i < n - 2; i++) {
// 跳过重复的固定数
if (i > 0 && num[i] == num[i - 1]) {
continue;
}
// 提前终止:如果当前固定的数已经大于0,由于数组已排序,后面的数都大于0
// 三数之和不可能为0,直接结束循环
if (num[i] > 0) {
break;
}
int left = i + 1;
int right = n - 1;
int target = -num[i]; // 需要找到两个数之和等于 -num[i]
while (left < right) {
int current_sum = num[left] + num[right];
if (current_sum == target) {
// 找到满足条件的三元组
result.push_back({num[i], num[left], num[right]});
// 跳过重复的左指针元素
while (left < right && num[left] == num[left + 1]) {
left++;
}
// 跳过重复的右指针元素
while (left < right && num[right] == num[right - 1]) {
right--;
}
// 移动指针寻找下一组
left++;
right--;
} else if (current_sum < target) {
left++;
} else {
right--;
}
}
}
return result;
}
};
核心思路
排序:先对数组排序,这样可以使用双指针技巧
固定一个数:遍历数组,对于每个数 num[i],在剩余部分寻找两个数使其和为 -num[i]
双指针:使用左右指针在排序后的数组中高效寻找匹配的数对
去重:在每一步都跳过重复元素,避免重复的三元组
时间复杂度
排序:O(n log n)
双指针遍历:O(n²)
总体:O(n²)
空间复杂度
结果存储:最坏情况 O(n²),但实际中远小于这个值
排序:O(log n)(快速排序的栈空间)
关键优化点
提前终止:当固定的数 num[i] > 0 时,由于数组已排序,后面的数都大于0,三数之和不可能为0
去重处理:在三个位置都进行了去重:
固定数 num[i] 的去重
左指针 num[left] 的去重
右指针 num[right] 的去重