给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = []
输出:[]
示例 3:
输入:nums = [0]
输出:[]
提示:
0 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
思路:
本题可以使用双指针的方法,但是首先遇到一个问题,就是这道题有3个数,所以我们可以首先把第一个数拎出来,这不就剩下两个指针了吗。
i为第一个数,j,k分别是第二,三个数,j为i下一个数,k为最后一个数。j和k是左右边界。
再来分析一下题目,因为不能是重复的组合,所以首先我们可以先进行排序,这样就不会轻易出现数字相同但是顺序不同的情况了。如果三者之和大于0就把k往左移,如果小于0,就把j往右移,直到两者相遇然后换下一个i来重置j和k重新进行查找。找到了等于0的时就把对应的数存到res中,
但是还要注意一个问题,避免重复,所以就是不能出现连续两个相同的数在前后两次查找中,所以在i,j++,k–的时候都要先进行判断,如果移动后的数与原数相等,就跳过该数,继续往下走,直到不同为止。
代码区:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int i=0;
sort(nums.begin(),nums.end());//首先进行从小到大排序,避免出现重复
vector<vector<int>> res;//等于二维数组
int n=nums.size();//n为nums的长度
if(n<3)return {};//如果n小于3,说明不可能满足条件,直接输出空
while(i<n-1){//将第一个数单独领出来,创造出双指针j,k的条件
int j=i+1;int k=n-1;//j为i下面一个数,k为最后一个数
while(j<k){//当两指针没有相遇时
if(nums[i]+nums[j]+nums[k]<0)//如果三数相加小于0说明应该使j再大一点,因为是排序好的
j++;
else if(nums[i]+nums[j]+nums[k]>0)//如果大于0就要将k小一点
k--;
else{//如果刚好等于0就是满足条件
res.push_back(vector<int>{nums[i],nums[j],nums[k]});//推入res中
j++;k--;//范围继续变小
while(j<k&&nums[j]==nums[j-1])//因为不能出现重复的,所以在这里如果遇到了相同的数就要跳过
j++;
while(j<k&&k<n-1&&nums[k]==nums[k+1])//同上
k--;
}
}
while(i<n-1&&nums[i]==nums[i+1])//i这个单独拎出来的数也要考虑不能重复,所以如果等于上一个数就要跳过
i++;
i++;//i+1,开始另一个组合的循环j,k
}
return res;//输出结果
}
};
新手上路,有错请指正;