题目
给你一个包含 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 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
解题方案
本题要求取得所有和为0的三元组,并且不能重复,因此选择对数组排序后,通过双指针法遍历数组,寻找所有不重复的和为0的三元组。需要注意各层循环的条件以及左右指针移动的条件。
循环条件:
- 遍历指针由
nums.begin()
循环至nums.end()-3
- 左右指针分别从
i+1
和nums.end()-1
开始,移动至重合
指针移动条件:
- 遍历指针
i>nums.begin()
且与i-1
处元素相等时i++
- 左指针
left>i+1
且与left-1
处值相等时left++
- 右指针
right<nums.end()-1
且与right+1
处的值相等时right--
- 三个指针处的值和小于0时
left++
- 三个指针处的值和大于0时
right--
该方法时间复杂度O(n^2)
C++代码:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
auto end = nums.end();
auto start = nums.begin();
vector<int>::iterator i, left, right;
if (nums.size()<3) return result;
sort(nums.begin(), nums.end());
for (i=start; i!=end-2 && *i<1; ++i) {
if (i>start && *i==*(i-1)) continue;
left = i+1;
right = end-1;
while (left!=right) {
if (left>i+1 && *left==*(left-1)){
left++;
continue;
}
if (right<end-1 && *right==*(right+1)){
right--;
continue;
}
if (*i+*left+*right<0) {
left++;
}
else if (*i+*left+*right==0) {
result.push_back({*i, *left, *right});
left++;
}
else {
right--;
}
}
}
return result;
}
};