题目描述
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
思路
- 首先将nums排序得到cp_nums,然后将cp_nums的数字依次压入,将三数之和专为两数之和的问题,需要注意的是压入数字时若出现重复则需要跳过,如上次压入的是-1,这次则不需要再压入,否则会重复。两数之和的求解用双指针,一个指向开头,一个指向结尾,和大于target则右指针左移,否则左指针右移,若相等则判断是否发生重复(比如0,0,0这种情况),若未重复则压入答案。
代码
方法一:
class Solution {
vector<int> res_p;
vector<vector<int>> res;
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<int> cp_nums;
if(nums.size()<3)
return res;
for(int i = 0; i < nums.size();i++)
cp_nums.push_back(nums[i]);
sort(cp_nums.begin(),cp_nums.end()); /*数字排序*/
for (int i = 0; i < cp_nums.size() - 2; i++)
{
if (i > 0 && cp_nums[i] != cp_nums[i - 1] || i == 0) /*避免重复压入求两数之和*/
{
vector<int> rest;
rest.assign(cp_nums.begin() + i + 1, cp_nums.end());
Twosum(rest, -cp_nums[i]);
}
}
return res;
}
void Twosum(vector<int> num, int target)
{
int record = num[0]-1; /*记录上次求得的两数之和的left指针指向的数*/
int left = 0, right = num.size()-1;
while(left<right)
{
if(num[left] + num[right] < target)
left++;
else if(num[left] + num[right] > target)
right--;
else
{
if(num[left] != record) /*避免重复压入*/
{
res_p.push_back(-target);
res_p.push_back(num[left]);
res_p.push_back(num[right]);
res.push_back(res_p);
res_p.clear();
record = num[left];
}
left++;
}
}
}
};