给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。
示例 1:
输入:nums = [1,1,2]
输出:
[[1,1,2],
[1,2,1],
[2,1,1]]
示例 2:
输入:nums = [1,2,3]
输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
提示:
1 <= nums.length <= 8
-10 <= nums[i] <= 10
这是一道求全排列的问题,之前有一道和这道题类似的题,那道题中不存在重复的数字,见 46. Permutations
先简单回顾一下之前求全排列的方法,即 46. Permutations 的解法,就是一道标准的递归题,代码如下所示:
class Solution {
public:
vector<vector<int>> permute(vector<int>& nums) {
vector<vector<int>> res;
helper(nums, 0, res);
return res;
}
void helper(vector<int>& nums, int start, vector<vector<int>>& res){
if(start == nums.size()){
res.push_back(nums);
return;
}
for(int i = start; i < nums.size(); i++){
swap(nums[start], nums[i]);
helper(nums, start+1, res);
swap(nums[start], nums[i]);
}
}
void swap(int& a, int& b){
int tmp = a;
a = b;
b = tmp;
}
};
具体分析如下,假如我们现在需要求的是 {1,2,3} 的全排列,那么过程如下:
现在假设序列中出现了一个重复数字,例如序列 {1, 2, 3, 2},为了区分其中的两个2,我们给它们分别取一个下标,于是序列可以表示成 {1, 2a, 3, 2b}
依然按照上面的方法,我们发现,存在以下2个情况:
但是我们会发现,{1, 3, 2b}的全排列 和 {2a, 3, 1}的全排列 是会重复的,问题出在哪呢?
仔细思考会发现,1和后面两个2交换效果其实是一样的,这势必会导致两次交换后会出现相同的全排列,为了解决这个问题,我们需要在一轮交换过程中排除那些重复的交换。
所以我们借助一个set(集合)来解决,于是,在存在相同数字的序列中求全排列的方法为:
class Solution {
public:
vector<vector<int>> permuteUnique(vector<int>& nums) {
vector<vector<int>> res;
helper(nums, 0, res);
return res;
}
void helper(vector<int>& nums, int start, vector<vector<int>>& res){
if(start == nums.size()){
res.push_back(nums);
return;
}
unordered_set<int> history;
for(int i = start; i < nums.size(); i++){
if(history.count(nums[i])) continue;
history.insert(nums[i]);
swap(nums[start], nums[i]);
helper(nums, start+1, res);
swap(nums[start], nums[i]);
}
}
void swap(int& a, int& b){
int tmp = a;
a = b;
b = tmp;
}
};
和之前的代码对比,发现只有下面几行代码不一样
unordered_set<int> history;
for(int i = start; i < nums.size(); i++){
if(history.count(nums[i])) continue;
history.insert(nums[i]);
原文:https://www.cnblogs.com/nullxjx/p/14978558.html