47. Permutations II(全排列 II)
1. 题目描述
给定一个可包含重复数字的序列,返回所有不重复的全排列。
示例:
输入: [1,1,2]
输出:
[
[1,1,2],
[1,2,1],
[2,1,1]
]
2. 递归 & 序号插入(Recursion & Insert by Index)
2.1 解题思路
这题和46. Permutations几乎是一样,只是这里可能会有重复的组合,那问题就简单了,我们还是沿用上题的思路,只是需要额外去除下重复的组合,这里应用了set的特性:set里面的元素都是唯一不重复的,最后拷贝set的内容到答案数组里面就OK啦。
2.2 实例代码
class Solution {
vector<vector<int>> ans;
vector<bool>* ifUsed = nullptr; // 这里使用了指针动态分配内存,但使用起来比较麻烦,大家可以自己换一种简单的方式存储bool数组
vector<int> temp;
set<vector<int>> ansPre;
// 1. 递归:recursionMethodUsingSwap和recursionMethodUsingBool,二选一即可
void recursionMethodUsingSwap(vector<int>& nums, int cur) {
if (cur == nums.size()) { ansPre.insert(nums); return; }
for (int i = cur; i < nums.size(); i++) {
swap(nums[cur], nums[i]);
recursionMethodUsingSwap(nums, cur + 1);
swap(nums[cur], nums[i]);
}
}
void recursionMethodUsingBool(vector<int>& nums) {
if (temp.size() == nums.size()) { ansPre.insert(temp); return; }
for (int i = 0; i < nums.size(); i++) {
if (!(*ifUsed)[i]) {
temp.push_back(nums[i]);
(*ifUsed)[i] = true;
recursionMethodUsingBool(nums);
temp.pop_back();
(*ifUsed)[i] = false;
}
}
}
// 2. 迭代:按序号插入元素
void insertElements(vector<int>& nums) {
if (!nums.size()) return;
this->ansPre.insert({ nums[0] });
for (int i = 1; i < nums.size(); i++) {
set<vector<int>> ans1;
for (const vector<int>& num : ansPre) {
for (int j = 0; j <= num.size(); j++) {
vector<int> arr = num;
arr.insert(arr.begin() + j, nums[i]);
ans1.insert(arr);
}
}
ansPre = ans1;
}
}
public:
~Solution() { delete(this->ifUsed); }
vector<vector<int>> permuteUnique(vector<int>& nums) {
// 1. recursion
// recursionMethodUsingSwap(nums, 0);
/*this->ifUsed = new vector<bool>(nums.size(), false);
recursionMethodUsingBool(nums);*/
// 2. iteration
insertElements(nums);
for (const vector<int>& v : this->ansPre) ans.push_back(v);
return this->ans;
}
};