三数之和
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
https://leetcode.cn/problems/3sum/description/
解题思路
1 最简单三层for循环 三层遍历
2 第一层for循环,固定第一个值,后续使用双指针 减少循环次数
代码
cpp
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
// 固定一个节点 后续使用双指针
// 求三元组 使和为0
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
// { { },{ },{ } }
vector<vector<int>> ans;
// 从小到大排序
sort(nums.begin(), nums.end());
for (int i = 0; i < n; i++)
{
// 从第二个开始 ,如何和前一个相同 向后
if (i > 0 && nums[i] == nums[i-1]) {
continue;
}
// 取 相反值 b + c + target = 0 --> b + c = -target
int target = -nums[i];
// 双指针 应该放在 for 外面 如果放在里面 每次 j 都会从头开始
int third = n - 1;
for (int j = i + 1; j < n; j++)
{
if(j > i+1 && nums[j] == nums[j-1])
{
continue;
}
// 由于是从小到大 排序的
while (third > j && nums[j] + nums[third] > target) {
third--;
}
if (third == j) {
break;
}
// 如果相加为0 才添加到数组中
if(nums[j] + nums[third] == target)
{
ans.push_back({ nums[i], nums[j], nums[third] });
}
}
}
return ans;
}
测试用例
cpp
int main() {
// 测试用例 1: 基础用例
vector<int> nums1 = { -1, 0, 1, 2, -1, -4 };
cout << "Test 1: [-1, 0, 1, 2, -1, -4]" << endl;
auto res1 = threeSum(nums1);
for (auto& v : res1) {
cout << " [" << v[0] << ", " << v[1] << ", " << v[2] << "]" << endl;
}
cout << "Expected: [-1, -1, 2] and [-1, 0, 1]" << endl << endl;
// 测试用例 2: 全是0
vector<int> nums2 = { 0, 0, 0, 0 };
cout << "Test 2: [0, 0, 0, 0]" << endl;
auto res2 = threeSum(nums2);
for (auto& v : res2) {
cout << " [" << v[0] << ", " << v[1] << ", " << v[2] << "]" << endl;
}
cout << "Expected: [0, 0, 0]" << endl << endl;
// 测试用例 3: 没有解
vector<int> nums3 = { 1, 2, 3, 4 };
cout << "Test 3: [1, 2, 3, 4]" << endl;
auto res3 = threeSum(nums3);
if (res3.empty()) {
cout << " No solution" << endl;
}
cout << "Expected: No solution" << endl << endl;
// 测试用例 4: 多个重复解
vector<int> nums4 = { -2, 0, 1, 1, 2 };
cout << "Test 4: [-2, 0, 1, 1, 2]" << endl;
auto res4 = threeSum(nums4);
for (auto& v : res4) {
cout << " [" << v[0] << ", " << v[1] << ", " << v[2] << "]" << endl;
}
cout << "Expected: [-2, 0, 2] and [-2, 1, 1]" << endl << endl;
// 测试用例 5: 空数组
vector<int> nums5 = {};
cout << "Test 5: []" << endl;
auto res5 = threeSum(nums5);
if (res5.empty()) {
cout << " No solution" << endl;
}
cout << "Expected: No solution" << endl << endl;
// 测试用例 6: 元素少于3个
vector<int> nums6 = { 0, 1 };
cout << "Test 6: [0, 1]" << endl;
auto res6 = threeSum(nums6);
if (res6.empty()) {
cout << " No solution" << endl;
}
cout << "Expected: No solution" << endl << endl;
// 测试用例 7: 大数测试
vector<int> nums7 = { -1, 0, 1, 2, -1, -4, 2, 2, -3 };
cout << "Test 7: [-1, 0, 1, 2, -1, -4, 2, 2, -3]" << endl;
auto res7 = threeSum(nums7);
for (auto& v : res7) {
cout << " [" << v[0] << ", " << v[1] << ", " << v[2] << "]" << endl;
}
cout << "Expected: [-4, 2, 2], [-3, 1, 2], [-1, -1, 2], [-1, 0, 1]" << endl << endl;
// 测试用例 8: 排序后相邻相等的情况
vector<int> nums8 = { -2, -2, -2, 1, 1, 1 };
cout << "Test 8: [-2, -2, -2, 1, 1, 1]" << endl;
auto res8 = threeSum(nums8);
for (auto& v : res8) {
cout << " [" << v[0] << ", " << v[1] << ", " << v[2] << "]" << endl;
}
cout << "Expected: [-2, 1, 1]" << endl << endl;
return 0;
}