链接:https://leetcode-cn.com/problems/3sum
题目详情:
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
分析:
根据两数之和的双指针法,我们可以通过枚举和数来构造等式,由于数组排序,我们每次贪心地去靠前的数字作为标志位,然后剩下的序列左右两边分别往中间扫,当三数和大于0则l++,小于0时r–,否则l++,r–,并加入答案集。由于要去重,每次偏移时要保证下一个数不和当前的数字重复,否则答案可能重复。
Code:
class Solution {
#define SZ(V) (int)V.size()
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
ans.clear();
sort(nums.begin(), nums.end());
//起码要有三个
for (int i = 0; i < SZ(nums) - 2; i++) {
if (nums[i] > 0) break;
if (i > 0 && nums[i] == nums[i-1]) continue; //去重
int left = i + 1;
int right = nums.size() - 1;
while (left < right) {
int sum = nums[left] + nums[right] + nums[i];
if (sum == 0) { //找到一组解
vector<int> tmp; tmp.clear();
tmp.push_back(nums[i]);;
tmp.push_back(nums[left]);;
tmp.push_back(nums[right]);;
ans.push_back(tmp);;
//把一样的解去重
while (left < right && nums[left] == nums[++left]);
while (right > left && nums[right] == nums[--right]);
} else if (sum < 0) { //说明不够凑成0, 左标右移
while (left < right && nums[left] == nums[++left]);
} else { //多了,右标左移
while (left < right && nums[right] == nums[--right]);
}
}
}
return ans;
}
};