题目链接
题目描述
给定一个包含 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
-105 <= nums[i] <= 105
解题思路
一开始想的是用map存储每个数字出现的次数,然后用双重循环,第三个元素用双重循环的前两个元素来代替,但是这样去重并不好完成,用map和set去重都不好完成
看了一下题解,可以先对数组进行排序,然后用一重循环来判断其中一个数,然后将这个数的负数设为target,然后让对撞指针代表的两个数的和等于target就可以代表三数之和为零
然后就是去重问题,这里我们选择的去重策略是让选择第一个不一样的数,也就是
if(i>0&&nums[i-1]==nums[i]) continue;
然后当三者之和等于0的时候,两个指针也要进行去重处理
当三者之和不等于0的时候, 其实并不需要对两个指针进行去重,因为去不去重并不影响结果
题解
class Solution {
public:
vector<vector<int>> v;
vector<vector<int>> threeSum(vector<int>& nums) {
if(nums.size()<3) return {};
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++){
if(i>0&&nums[i-1]==nums[i]) continue;
int j=i+1;
int sum=-nums[i];
int k=nums.size()-1;
while(j<k){
if(nums[i]+nums[j]+nums[k]==0){
v.push_back({nums[i],nums[j],nums[k]});
/*这个地方代表
while(j<k){
j++;
if(&&nums[j-1]!=nums[j]) break;
}
*/
while(j<k&&nums[j]==nums[++j]);
while(j<k&&nums[k]==nums[--k]);
}else if(nums[k]+nums[j]>sum){
//不相同可以不用去重
k--;
}else{
//不相同可以不用去重
j++;
}
}
}
return v;
}
};