题目描述
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums =
[-1, 0, 1, 2, -1, -4]
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
在一个有序区间内寻找两个加和等于定值的数,可以用尺取法(双指针),即左右指针加和大,右指针左移,加和小,左指针右移,复杂度为O(n),对于三个数,我们只需要
- 穷举第一个数字
number1
- 问题变成在这个数字后面的区间找
两数之和=target-number1
- 在这个数字后面的区间用双指针找到给定的目标值
注意:
因为双指针要求数组有序,我们必须将数组排序
去重:
排序之后的数组是有序的,意味着相同的元素都连在一起,可是我们不希望选取相同的元素
- 对于穷举第一个数字,我们令它不等于它的前一个数字即可做到去重
- 对于双指针找第二第三,一旦找到两个合法的数
n2, n3
,左指针一直向右,直到找到一个不同于n2
的数,右指针一直向左,直到找到一个不同于n3
的数
注意去重的时候,要判断边界情况,否则容易导致越界
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums)
{
vector<vector<int> > ans;
sort(nums.begin(), nums.end());
for(int i=0; i<nums.size(); i++)
{
// 第一个数去重
if(i==0 || nums[i]!=nums[i-1])
{
int l = i+1;
int r = nums.size()-1;
while(l<r)
{
if(nums[i]+nums[l]+nums[r]>0)
{
r--; continue;
}
if(nums[i]+nums[l]+nums[r]<0)
{
l++; continue;
}
if(nums[i]+nums[l]+nums[r]==0)
ans.push_back(vector<int>{nums[i], nums[l], nums[r]});
// 第二三个数去重
while(l+1<nums.size() && nums[l]==nums[l+1])
l++;
while(0<=r-1 && nums[r]==nums[r-1])
r--;
l++; r--;
}
}
}
return ans;
}
};