本文讲解题目一种解法,遍历加双指针法。时间复杂度O(n2),空间复杂度O(log n)(不计算输入输出空间)
思路
看到这个题目容易让人想到两数之和,会想要使用类似的方法,确实如此。而且根据输入范围可知,时间复杂度至高可以达到 n2logn ,可以使用比较暴力的方法。
那么可以发现,如果固定一个数之后,就可以转换为两数之和了,又因为要求找到所有答案,所以使用双指针暴力查找就可以。
那么整体就应该是外层遍历第一个数,双指针查找后两个数,时间复杂度就是 n2。
实现
确定整体实现后,接下来就是考虑怎么具体实现了。
首先需要排序,然后每次遍历一个数,双指针范围就是这个数的右侧。
接下来是关键的去重,首先看为什么会有重复:存在相同的数,所有只需要跳过所有重复的数就可以。
那么具体就分两种,1 外层循环遍历时如果与前一个数字相同就跳过,2 内层循环当出现结果时,如果和下一个数相同就继续移动指针。
需要注意的比较中需要防止越界。
代码
cpp
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<vector<int>>ans;
int n=nums.size();
for(int i=0;i<n-2;i++){
if (i > 0 && nums[i] == nums[i - 1]) continue;
int l=i+1;
int r=n-1;
while(l<r){
int sum=nums[l]+nums[r]+nums[i];
if(sum==0){
ans.push_back({nums[i],nums[l],nums[r]});
while(l<r&&nums[l]==nums[l+1])l++;
while(l<r&&nums[r]==nums[r-1])r--;
l++;
r--;
}else if(sum>0){
r--;
}else{
l++;
}
}
}return ans;
}
};
总结
这题就是一个双指针题目,但是需要注意去重,整体不难想。最开始我用的时单独变量存储,判断去重结果复杂而且漏查。
只要发现重复来源为重复数字,直接跳过就可以,然后就可以做出来了。