题目描述:
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
学习:
做完11题过来的,选了个双指针想练练,发现是一点都不会i,因为要求没有重复,所以思索用unordered_set进行查找,但是这样的问题是,重复的元素并不能直接去掉,因为比如-1+-1+2=0我们是需要使用的,需要两个循环,也用不了双指针...还是去学习一下吧
答案采取了排序+双指针。首先排序其实和unordered_set作用差不多的,因为能够很方便的进行查找,同时也保留了重复的数字,所以在这题里比较适用。固定指针+双指针用来寻找,还是这个佬!!
and发现自己连排序都不会了....下面代码是这篇文章的代码,自学一下,首先排序可以采用自带方案sort函数,然后要注意边界值的情况,比如空的时候返回的问题,然后注意一点在循环中判断左右指针移动的时候,我是这样的,然后就报--时间超时,可以看到这个uu用tem[]记录后判断会减少很多访问,就可以通过!
23.5.29补充:猛然发现这里报报超时可能并不是方法不够好,只是因为方法不对,但语法不错,所以一直重复运行而错的。这里应该如下,需要对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());
//声明三个指针,既索引
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;
}
};