「这是我参与2022首次更文挑战的第15天,活动详情查看:2022首次更文挑战」。
题目分析
给你一个包含 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]]
思路分析
三数之和为0,如果不存在都是0的情况,当然了也说过不可以包含重复的三元组。那就一定是一个正数,两个负数。或者两个正数一个负数,或者一个正数一个负数一个0
那么第一时间想到的是根据正负数分为两个数组,遍历之前说到的那些可能。
然而这样并没有显著降低时间复杂度。为了降低时间复杂度,我们可以考虑对数组进行排序,排序后先选择一个元素,再根据双指针选择另两个元素。
由于这道题特别强调了重复的问题,所以需要考虑一个复杂情况
[0,0,0,0]
首先是第一个元素遍历时,必须遍历不重复的元素(因为是排序过的数组所以很好判断)
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
同样方式限制双指针的第一个就可以了。
具体实现
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ret;
sort(nums.begin(), nums.end());
int n = nums.size();
for(int i = 0; i < n - 2; i++){
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
if(nums[i] > 0 ) return ret;
int sum = nums[i];
int k = n - 1;
for (int j = i + 1; j < n - 1; j ++){
if (j > i+1 && nums[j] == nums[j - 1])continue;
while(j < k && nums[j] + nums[k] + sum > 0){
k--;
}
if(j == k)break;
if( nums[j] + nums[k] + sum == 0){
ret.push_back({nums[i], nums[j], nums[k]});
}
}
}
return ret;
}
总结
由于双指针实际上相当于访问了一次数组,因此相当于n^2+ nlogn的复杂度,也就是n^2