轉自這位大神。
啥也不說了.
看了大神的代碼,感覺就像柯南破案的時候,腦袋中有一道閃電劃過一樣。
[1,2,3]
have the following permutations:[1,2,3]
, [1,3,2]
, [2,1,3]
, [2,3,1]
, [3,1,2]
,
and [3,2,1]
.當只有1時候:[1]
當加入2以後:[2, 1], [1, 2]
當加入3以後:[3, 2, 1], [2, 3, 1], [2, 1, 3], [3, 1, 2], [1, 3, 2], [1, 2, 3]
前3個permutation分別對應將3插入[2, 1]的0, 1, 2的位置。同理後3個爲插入[1, 2]的。
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int>> allPer;
if(num.empty()) return allPer;
allPer.push_back(vector<int>(1,num[0]));
for(int i=1; i<num.size(); i++) {
int n = allPer.size();
for(int j=0; j<n; j++) {
for(int k=0; k<allPer[j].size(); k++) {
vector<int> per = allPer[j];
per.insert(per.begin()+k, num[i]);
allPer.push_back(per);
}
allPer[j].push_back(num[i]);
}
}
return allPer;
}
};
方法2:backtracking法
class Solution {
public:
vector<vector<int> > permute(vector<int> &num) {
vector<vector<int>> allPer;
if(num.empty()) return allPer;
vector<bool> used(num.size(), false);
vector<int> per;
findPermutations(num, used, per, allPer);
return allPer;
}
void findPermutations(vector<int> &num, vector<bool> &used, vector<int> &per, vector<vector<int>> &allPer) {
if(per.size()==num.size()) {
allPer.push_back(per);
return;
}
for(int i=0; i<num.size(); i++) {
if(used[i]) continue;
used[i] = true;
per.push_back(num[i]);
findPermutations(num, used, per, allPer);
used[i] = false;
per.pop_back();
}
}
};
題目鏈接在此
[1,1,2]
have the following unique permutations:[1,1,2]
, [1,2,1]
,
and [2,1,1]
.與I的區別在於有重複元素,所以在解集中要去重複。
通過排序 + 每層遞歸跳過重複數字。
注意這裏的重複數字指的是一直到當前遞歸層,還未被使用的數字中的重複。
class Solution {
public:
vector<vector<int> > permuteUnique(vector<int> &num) {
vector<vector<int>> allPer;
if(num.empty()) return allPer;
sort(num.begin(),num.end());
vector<int> per;
vector<bool> used(num.size(),false);
findPerUniq(num, used, per, allPer);
return allPer;
}
void findPerUniq(vector<int> &num, vector<bool> &used, vector<int> &per, vector<vector<int>> &allPer) {
if(per.size()==num.size()) {
allPer.push_back(per);
return;
}
for(int i=0; i<num.size(); i++) {
if(used[i]) continue;
if(i>0 && num[i]==num[i-1] && !used[i-1]) continue;
used[i] = true;
per.push_back(num[i]);
findPerUniq(num, used, per, allPer);
per.pop_back();
used[i] = false;
}
}
};
關於全排列,還有一種比較直觀能理解的方法。參見這個。