题目介绍:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路:
1.暴力求解
使用3个for循环,找到所有相加等于零的vector,然后对每一个vector做一个sort后再判断是否相等,相等则erase
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//3个for循环,找到所有相加等于零的vector之后对每一个vector做一个排序然后判断是否相等,erase掉相同的元素
class Solution
{
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int>> result;//保存最后结果
vector<int> temp;//保存每一个找到的结果
int len = nums.size();
int sum = 0;
for(int m = 0; m < len; m++)
{
for(int n = m + 1; n<len ; n++)
{
for(int o = n + 1; o < len; o++)
{
sum = nums[m] + nums[n] + nums[o];
if(sum == 0)
{
temp.push_back(nums[m]);//将一个新的元素加到vector的最后面
temp.push_back(nums[n]);
temp.push_back(nums[o]);
result.push_back(temp);
temp.clear();
}
sum = 0;
}
}
}
int l = result.size();
for(int x = 0; x < l; x++)
{
sort(result[x].begin(), result[x].end());//对,result保存的每一个数组进行排序
}
for(int y = 0; y < l; y++)
{
for(int z = y + 1; z < l; z++)
{
if(result[y] == result[z])
{
result.erase(result.begin() + z);
l--;
z--;
}
}
}
return result;
}
};
int main()
{
vector<int> b = {0,0,0,0};
Solution a;
vector<vector<int>> result = a.threeSum(b);
for(int i=0; i<result.size(); i++)
{
cout << "{" ;
for(int j=0; j<result[i].size(); j++)
{
cout << result[i][j] << ",";
}
cout << "}" << endl;
}
return 0;
}
2.对输入的数字先做一个排序,对负数部分进行循环, 看其后面的两数相加是否能与它抵消,当然如果第一个数就是正数就是无解的输入 。在计算后面两数的和的时候我们可以设两个迭代器, 一个从这个数后第一个数开始,一个从最后一个数开始, 如果加和小了就移动第一个迭代器,如果加和大了就移动第二个迭代器,就可以遍历所有情况了。 而且因为数字整个都是排序的,如果有重复数字肯定是相邻的, 我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
/*对输入的数字先做一个排序,对负数部分进行循环,
* 看其后面的两数相加是否能与它抵消,当然如果第一个数就是正数就是无解的输入
* 在计算后面两数的和的时候我们可以设两个迭代器,
* 一个从这个数后第一个数开始,一个从最后一个数开始,
* 如果加和小了就移动第一个迭代器,如果加和大了就移动第二个迭代器,就可以遍历所有情况了。
* 而且因为数字整个都是排序的,如果有重复数字肯定是相邻的,
* 我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。
*/
class Solution
{
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int>> res;//保存最后结果
sort(nums.begin(), nums.end());//升序,一般情况第一个就是这个数组里面最小的一般小于等于0
for(int k = 0; k < nums.size(); ++k)
{
if(nums[k] > 0)
break;//结束整个循环
if(k > 0 && nums[k] == nums[k-1])
continue;//结束本次循环
int target = 0-nums[k];//第一次把元素 变成正数
int i = k+1, j = nums.size()-1;//i指向下一个元素,j指向最后一个元素
while(i < j)
{
if(nums[i] + nums[j] == target)//找到符合要求的值,可以看出a + b + c = 0 转化为 判断 a+b是否等于c
{
res.push_back({nums[k], nums[i], nums[j]});
/*因为数字整个都是排序的,如果有重复数字肯定是相邻的,我们在处理完前一个数之后,如果后一个数与之相等就删掉,这样避免了重复情况的出现。*/
while(i < j && nums[i] == nums[i+1]) ++i;
while(i < j && nums[j] == nums[j-1]) --i;
++i;
--j;
}
else if(nums[i] + nums[j] < target) ++i;
else --j;
}
}
return res;
}
};
int main()
{
vector<int> b = {-1, 0, -1, 2, 1, -4};
Solution a;
vector<vector<int>> result = a.threeSum(b);
for(int i=0; i<result.size(); i++)
{
cout << "{" ;
for(int j=0; j<result[i].size(); j++)
{
cout << result[i][j] << ",";
}
cout << "}" << endl;
}
return 0;
}