问题描述
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请
你返回所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
提示:
3 <= nums.length <= 3000
-10^5 <= nums[i] <= 10^5
示例
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。
示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。
示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。
# 解题思路
此题一般用三个 `for` 循环即可解决,但是题目要求答案不能重复。因此,要么使用一个集合来保存已经记录过的答案,要么添加约束条件,使保存的答案不会重复。这里我们选择第二种方法,初始的 `nums` 是一个无序列表,我们可以对其进行排序,就可以保证答案中 `a <= b <= c` 成立。这样每次添加的解 `{a,b,c}` 也能保证有序。
然后,还可能存在如 `nums=[0,0,0,0]` 的情况,我们还需记录本次循环与上一次循环时的解是否一致,一致的话就不需要再搜索了。
既然需要对原数组进行排序,又需要保证不重复遍历,那我们可以考虑使用 `map` 来记录每个不同的元素。由于 `map` 是有序的,我们遍历时也能保证不会遍历到重复的结果。
``` C++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> res;
map<int, int> mp;
for(int i = 0; i < nums.size(); i++){
mp[nums[i]]++; //统计每个元素的出现次数
}
int tmp;
for(auto i = mp.begin(); i != mp.end(); i++){
if(i->first > 0){ // i->first <= j->first <= tmp,因此i->first <= 0
break;
}
i->second--;
for(auto j = i; j != mp.end(); j++){
if(j->first + i->first > 0){ // 第三个数一定大于前两个数,因此前两个数的和一定要<=0
break;
}
if(j->second){
tmp = -(i->first + j->first);
if(tmp >= j->first){
if(tmp == j->first && j->second > 1){ // 判断第二,第三个数相等的情况
res.push_back({i->first, tmp, tmp});
}
else if(tmp > j->first && mp.count(tmp)){ // 第二,第三个数不等的情况
res.push_back({i->first, j->first, tmp});
}
}
}
}
}
return res;
}
};
标签:tmp,15,nums,三数,示例,三元组,力扣,mp,first
From: https://www.cnblogs.com/greatestchen/p/16942557.html