文章目录
- 1.题目
- 示例
- 提示
- 2.解答思路
- 3.实现代码
- 结果
- 4.总结
1.题目
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例
提示
2.解答思路
提取已知信息:
1.本题就是求三个数之和为0,
2.并且三个数的下标不能相等,
3.最后答案的集合互不相同。
思路:
1.首先对vector对象进行排序后,有利于去重操作。简单情况直接返回空集合。
其中:
vector.empty()//返回对象是否为空,若空,返回true,否则,返回false
vector.front()//返回vector对象第一个元素值
vector.back()//返回vector对象最后一个元素值
2.设三个变量分别代表三个元素下标,(双指针需要有一个固定的值)
因此令第一个值为 i , 去遍历另外两个下标head,tail
如果有相同的元素重复出现,第一次正常遍历,后面就都可以跳过了(对 i 和 head 一样的道理)
3.设a为两个指针下标对应元素需要相加的和
当head+tail对应的值大于a,tail减一
当head+tail对应的值小于a,head加一
注意:三个下标不能相等,因此若head==tail,直接跳出双指针循环,
当head+tail对应的值等于a时,把三个元素添加到答案ans中 ans.push_back({nums[i],nums[head],nums[tail]});
3.实现代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums){
int n=nums.size();
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
if(nums.empty() || nums.front()>0 || nums.back()<0)
return {};
for(int i =0;i <n-2;++i ){//i作为第一个数的下标
//需要和上一次枚举的数不相同,去重,避免重复答案
//当下标i-1和i一样,并且i已经计算过一次(i>0)时,可以直接跳过
if(i >0 && nums[i] == nums[i-1] )
{
continue;
}
int head,tail;//此处使用双指针,head是i+1,tail是最后一个元素
int a=-nums[i];//nums[head]+nums[tail]=0-nums[i] 是固定,对于下面的循环
for(head=i+1,tail=n-1;head < tail ;++head)
{
//需要和上一次枚举的数不相同,避免重复答案
if (head > i + 1 && nums[head] == nums[head - 1])
//当下标head-1和head一样,并且head已经计算过一次(head>i+1)时,可以直接跳过
continue;
//tail前移的条件
while(head <tail && nums[head]+nums[tail]>a){
--tail;
}
//如果指针重合,随着head后续增加
//就不会有满足条件的,可以退出循环
//要求有三个下标不能相同
if(head == tail)
break;
if(nums[head]+nums[tail] == a)
ans.push_back({nums[i],nums[head],nums[tail]});
}
}
return ans;
}
};
结果
用时不止两个半小时,找出答案还好,后面的去重难住了很久,很难在自己的代码上修改成功,后来也是参考了别人的代码思路,然后又重写的。
4.总结
这个题有个bug就是,我的内层循环使用while就会时间超时,for循环就不会超时,就是第二个for循环的位置。暂时还没弄明白,不过以后遇到时间超时的时候,可以试一试换一个循环语句。
自信,坚持,upup~