# LeetCode 15. 三数之和 - C++ 实现
## 解题思路:排序 + 双指针
```
1. 对数组排序
2. 固定第一个数 nums[i],双指针在 [i+1, n-1] 中找两数之和 = -nums[i]
3. 三处去重,避免重复三元组
```
**时间复杂度**: O(n²)
**空间复杂度**: O(log n)(排序栈空间)
---
## C++ 实现
```cpp
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
int n = nums.size();
if (n < 3) return result;
sort(nums.begin(), nums.end()); // 排序
for (int i = 0; i < n - 2; i++) {
// ① 去重:跳过重复的第一个数
if (i > 0 && nums[i] == nums[i - 1])
continue;
// ② 剪枝:最小值 > 0,后面不可能有解
if (nums[i] > 0)
break;
int left = i + 1;
int right = n - 1;
int target = -nums[i]; // 需要找的两数之和
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
result.push_back({nums[i], nums[left], nums[right]});
// ③ 去重:跳过重复的左指针值
while (left < right && nums[left] == nums[left + 1])
left++;
// ③ 去重:跳过重复的右指针值
while (left < right && nums[right] == nums[right - 1])
right--;
left++;
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
}
return result;
}
};
```
---
## 测试代码
```cpp
#include <iostream>
int main() {
Solution sol;
// 测试用例 1
vector<int> nums1 = {-1, 0, 1, 2, -1, -4};
vector<vector<int>> res1 = sol.threeSum(nums1);
cout << "Test 1: ";
for (auto& v : res1) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: [-1, -1, 2] [-1, 0, 1]
cout << endl;
// 测试用例 2
vector<int> nums2 = {0, 1, 1};
vector<vector<int>> res2 = sol.threeSum(nums2);
cout << "Test 2: ";
for (auto& v : res2) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: (空)
cout << endl;
// 测试用例 3
vector<int> nums3 = {0, 0, 0};
vector<vector<int>> res3 = sol.threeSum(nums3);
cout << "Test 3: ";
for (auto& v : res3) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: [0, 0, 0]
return 0;
}
```
---
## 关键要点总结
| 要点 | 说明 |
|------|------|
| 排序 | `sort(nums.begin(), nums.end())` |
| 剪枝 | `nums[i] > 0` 时直接 break,因为后面全是正数 |
| 去重① | `i > 0 && nums[i] == nums[i-1]` 跳过重复第一个数 |
| 去重②③ | 找到解后,left/right 跳过相同值再移动 |
| 边界 | `n < 3` 直接返回空 |
---
## 执行流程图解
```
排序后: [-4, -1, -1, 0, 1, 2]
i=0: nums[i]=-4, target=4
left=1,right=5: -1+2=1 < 4 → left++
left=2,right=5: -1+2=1 < 4 → left++
left=3,right=5: 0+2=2 < 4 → left++
left=4,right=5: 1+2=3 < 4 → left++
left=5,right=5: 结束
i=1: nums[i]=-1, target=1
left=2,right=5: -1+2=1 ✓ → [-1,-1,2]
left=3,right=4: 0+1=1 ✓ → [-1, 0,1]
i=2: nums[i]=-1, 与i=1相同 → skip
i=3: nums[i]=0, target=0
left=4,right=5: 1+2=3 > 0 → right--
left=4,right=4: 结束
```
# LeetCode 15. 三数之和 - C++ 实现
## 解题思路:排序 + 双指针
```
1. 对数组排序
2. 固定第一个数 nums[i],双指针在 [i+1, n-1] 中找两数之和 = -nums[i]
3. 三处去重,避免重复三元组
```
**时间复杂度**: O(n²)
**空间复杂度**: O(log n)(排序栈空间)
---
## C++ 实现
```cpp
#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
int n = nums.size();
if (n < 3) return result;
sort(nums.begin(), nums.end()); // 排序
for (int i = 0; i < n - 2; i++) {
// ① 去重:跳过重复的第一个数
if (i > 0 && nums[i] == nums[i - 1])
continue;
// ② 剪枝:最小值 > 0,后面不可能有解
if (nums[i] > 0)
break;
int left = i + 1;
int right = n - 1;
int target = -nums[i]; // 需要找的两数之和
while (left < right) {
int sum = nums[left] + nums[right];
if (sum == target) {
result.push_back({nums[i], nums[left], nums[right]});
// ③ 去重:跳过重复的左指针值
while (left < right && nums[left] == nums[left + 1])
left++;
// ③ 去重:跳过重复的右指针值
while (left < right && nums[right] == nums[right - 1])
right--;
left++;
right--;
}
else if (sum < target) {
left++;
}
else {
right--;
}
}
}
return result;
}
};
```
---
## 测试代码
```cpp
#include <iostream>
int main() {
Solution sol;
// 测试用例 1
vector<int> nums1 = {-1, 0, 1, 2, -1, -4};
vector<vector<int>> res1 = sol.threeSum(nums1);
cout << "Test 1: ";
for (auto& v : res1) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: [-1, -1, 2] [-1, 0, 1]
cout << endl;
// 测试用例 2
vector<int> nums2 = {0, 1, 1};
vector<vector<int>> res2 = sol.threeSum(nums2);
cout << "Test 2: ";
for (auto& v : res2) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: (空)
cout << endl;
// 测试用例 3
vector<int> nums3 = {0, 0, 0};
vector<vector<int>> res3 = sol.threeSum(nums3);
cout << "Test 3: ";
for (auto& v : res3) {
cout << "[";
for (int j = 0; j < v.size(); j++) {
cout << v[j] << (j < v.size()-1 ? ", " : "");
}
cout << "] ";
}
// 输出: [0, 0, 0]
return 0;
}
```
---
## 关键要点总结
| 要点 | 说明 |
|------|------|
| 排序 | `sort(nums.begin(), nums.end())` |
| 剪枝 | `nums[i] > 0` 时直接 break,因为后面全是正数 |
| 去重① | `i > 0 && nums[i] == nums[i-1]` 跳过重复第一个数 |
| 去重②③ | 找到解后,left/right 跳过相同值再移动 |
| 边界 | `n < 3` 直接返回空 |
---
## 执行流程图解
```
排序后: [-4, -1, -1, 0, 1, 2]
i=0: nums[i]=-4, target=4
left=1,right=5: -1+2=1 < 4 → left++
left=2,right=5: -1+2=1 < 4 → left++
left=3,right=5: 0+2=2 < 4 → left++
left=4,right=5: 1+2=3 < 4 → left++
left=5,right=5: 结束
i=1: nums[i]=-1, target=1
left=2,right=5: -1+2=1 ✓ → [-1,-1,2]
left=3,right=4: 0+1=1 ✓ → [-1, 0,1]
i=2: nums[i]=-1, 与i=1相同 → skip
i=3: nums[i]=0, target=0
left=4,right=5: 1+2=3 > 0 → right--
left=4,right=4: 结束
```