一、题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
二、思路
排序+双指针,每次选一个中心位,从两边开始分别选择一个数,与中心位相加,如果等于0则加入容器中,然后依次遍历所有数作为中心位,可算出所有结果。时间复杂度为O( n 2 n^2 n2)。
需要注意的是边界问题,和如何去除重复的情况。
此处用到的一个方法是对于重复的中心位只遍历一次(以重复数字最左边那个为中心位),而当中心位有重复数字的时候,允许左指针指向中心位,此时需要考虑三个0的特殊情况。
三、代码
代码如下:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
if(nums.size()>0) sort(nums.begin(),nums.end());
else return res;
//需考虑输入为空的情况
int l,m,r,n;
for(m=1;m<nums.size()-1;m++){
l=0;
r=nums.size()-1;
while(m<r&&(m>l||(nums[m+1]==nums[m]&&m==l))&&nums[l]<=0&&nums[r]>=0){
//左指针小于中心位且不大于0,右指针大于中心位且不小于0,当中心位有重复数字的时候,左指针可以等于中心位
n=nums[l]+nums[m]+nums[r];
if(n==0){
if(!nums[r]&&m==l&&(m+2>nums.size()-1||(m+2<=nums.size()-1&&nums[m+2]))) break;
//如果0只有两次重复,则不存在满足条件现象
res.push_back({nums[l],nums[m],nums[r]});
}
while(nums[r-1]==nums[r]&&m<r){r--;}
//右指针对于重复的数字,向左滑
if(m==r) r++;
//如果右指针滑倒了与中心位相同的地方则需要向右移一次指针,否则会跳出循环
while(nums[l+1]==nums[l]&&l<m){l++;}
//左指针对于重复的数字,向右滑
if(n>=0) r--;
if(n<=0) l++;
//当不满足等于0的时候,分别滑动左右两指针
}
while(m<nums.size()-1&&nums[m+1]==nums[m]){m++;}
//对于重复的中心位数字,直接滑走
}
return res;
}
};
总结
双指针问题着重需要考虑边界条件