Given a collection of numbers that might contain duplicates, return all possible unique permutations.
For example,
[1,1,2]
have the following unique permutations:
[1,1,2]
, [1,2,1]
, and [2,1,1]
.
两种解答
1、搜索 + hash
2、 搜索 + 剪枝
2 比1快大概10倍
class Solution_1 {
public:
vector<vector<int> > permuteUnique(vector<int> &num) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
list<int> numl(num.begin(),num.end());
vector<vector<int>> re;
set<vector<int>> set_re;
vector<int> partialPemu;
doPermute(partialPemu, numl, set_re);
re.insert(re.end(), set_re.begin(), set_re.end());
return re;
}
private:
void doPermute(vector<int>& partialPemu, list<int>& num, set<vector<int>>& set_re){
if(num.empty()){
//re.push_back(partialPemu);
if(set_re.count(partialPemu) == 0)
set_re.insert(partialPemu);
return;
}
int n = num.size();
for(int i = 0; i < n; i++){
int curval = num.front();
num.pop_front();
partialPemu.push_back(curval);
doPermute(partialPemu, num, set_re);
partialPemu.pop_back();
num.push_back(curval);
}
}
};
class Solution_2 {
public:
struct Num{
int val;
int occur;
Num(): val(0),occur(0){}
Num(int v, int o): val(v),occur(o){}
};
vector<vector<int> > permuteUnique(vector<int> &num) {
std::sort(num.begin(), num.end());
list<Num> numl;
int total = 0;
for(int i = 0; i < num.size();){
Num curnum(num[i], 1);
i++;
while(i < num.size() && num[i - 1] == num[i]){
curnum.occur++;
i++;
}
//cout << "val = " << curnum.val << ", occur = " << curnum.occur << endl;
total += curnum.occur;
numl.push_back(curnum);
}
//assert(total != num.size());
vector<int> partialPemu;
vector<vector<int> > re;
doPermute(num.size(), partialPemu, numl, re);
return re;
}
private:
void doPermute(int n, vector<int>& partialPemu, list<Num>& num, vector<vector<int>>& re){
if(num.empty()){
re.push_back(partialPemu);
return;
}
int i = 0;
while(i < n){
Num curNum = num.front();
if(!partialPemu.empty() && partialPemu.back() == curNum.val){
num.pop_front();
num.push_back(curNum);
i += curNum.occur;
}else{
Num curNum = num.front();
for(int occur = 1; occur < curNum.occur; occur++){
partialPemu.push_back(curNum.val);
num.front().occur = curNum.occur - occur;
int m = n - occur;
doPermute(m, partialPemu, num, re);
}
partialPemu.push_back(curNum.val);
num.pop_front();
int m = n - curNum.occur;
doPermute(m, partialPemu, num, re);
popn(partialPemu, curNum.occur);
num.push_back(curNum);
i += curNum.occur;
}
}
}
private:
void popn(vector<int>& nums, int n){
while(n--)
nums.pop_back();
}
};