![](https://i-blog.csdnimg.cn/blog_migrate/fc3c6ef7873b528291d21315aaf66242.png)
【题解】
双指针
注:
1.定义一个二位数组存储结果集
2.对输入数组进行升序
3.去重(主要考虑三个数的去重。 a, b ,c, 对应的就是 nums[i],nums[left],nums[right])
(1)对a去重:
判断 nums[i] 与 nums[i + 1]是否相同,还是判断 nums[i] 与 nums[i-1] 不一样,一个是对后一个判断,一个是对前一个判断
使用nums[i]==nums[i+1],例如{-1, -1 ,2} 这组数据,当遍历到第一个-1 的时候,判断 下一个也是-1,那这组数据就pass了。将会漏掉-1,-1,2 这种情况。
我们要做的是 不能有重复的三元组,但三元组内的元素是可以重复的!
nums[i] == nums[i-1]当遍历到 第一个 -1 的时候,只要前一位没有-1,那么 {-1, -1 ,2} 这组数据一样可以收录到 结果集里。
(2)b与c的去重
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;//存储结果集
sort(nums.begin(),nums.end());//将输入数组进行升序
for(int i = 0; i < nums.size(); i++){
//因为数组是升序,当i(第一个数)>0时,后面两个数肯定大于零,所以三个数相加不可能等于零,直接返回空的result
if(nums[i] > 0){
return result;
}
//i>0是防止数组下标出现负数情况,使用nums[i]==nums[i+1]将会漏掉-1,-1,2 这种情况,所以使用nums[i] == nums[i-1]
if(i > 0 && nums[i] == nums[i-1]){
continue;//去重a
}
int left = i + 1;
int right = nums.size() - 1;
//当right=left的时候,指向的是同一个元素,那么就变成了二元组相加,而不是三元组相加
while(right > left){
if(nums[i] + nums[left] + nums[right] > 0) right--;//三数之和大于零
else if(nums[i] + nums[left] + nums[right] < 0) left++;//三数之和小于零
//三数之和等于零
else{
//先返回一个结果集
result.push_back(vector<int>{nums[i], nums[left], nums[right]});
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while(right > left && nums[left] == nums[left+1]) left++;
while(right > left && nums[right] == nums[right-1]) right--;
// 找到答案时,双指针同时收缩
left++;
right--;
}
}
}
return result;
}
};