题目描述:
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
主要思路:
(1)对于在一个数组中找到两个数之和为0的方法:可以先将数组进行排序nums,再使用双指针,分别指向第一个元素left和最后一个元素right,则比较nums[left]+nums[right]和0 的关系:
(a)若是等于零,则表示这两个元素满足要求;
(b)若是小于零,则说明这两个值之和需要增大,则++left;
(c)若是大于零,则说明这两个值之和需要减小,则–right;
(2)该问题描述中需要的是三个数之和为零,则可以增加一个新的指针now,指向第一个数,则left和right可以在此基础上,使用上述方法,处理now之后的所有的可能的组合,则当将now从头到尾遍历了,也就获得了所有的可能的组合;
(3)由于需要处理重复的组合的情形,故需要在获得满足要求的组合后,对后面的可能和left或right指向的值相等的元素,进行跳过;
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
//处理特殊的情形
if(nums.size()<3)
return vector<vector<int>>();
//排序
sort(nums.begin(),nums.end());
//处理特殊的情形
if(nums[0]>0||nums[nums.size()-1]<0)
return vector<vector<int>>();
//声明三个指针,既索引
int now=0;
int left=now+1;
int right=nums.size()-1;
vector<vector<int>> result;
//使用now遍历元素
while(now<nums.size()-2){
//声明临时变量存储当前的以now为开头的三个元素的可能的组合
vector<int>tmp(3);
tmp[0]=nums[now];
//left和right的初值,既遍历now之后的范围
left=now+1;
right=nums.size()-1;
while(left<right){
if(nums[now]+nums[left]+nums[right]==0){
tmp[1]=nums[left];
tmp[2]=nums[right];
result.emplace_back(tmp);
//去除重复的情形
while(left<right&&nums[left]==tmp[1])
++left;
while(right>left&&nums[right]==tmp[2])
--right;
}
else if(nums[now]+nums[left]+nums[right]<0){
++left;
}
else{
--right;
}
}
//去除重复的情形
while(now<nums.size()-2&&nums[now]==tmp[0])
++now;
}
return result;
}
};