要求对数组a[] = {1, 2, 3, 4, 4}进行全排列(去重和不去重)。
这里提供三种代码。
[TOC]
C++的next_permutation
<algorithm>
中的next_permutation可实现去重的全排列
————————————————————————————
1 2 3 4 5 6 7 8
| void solve(){ do{ for(int i = 0; i < 5; ++i){ cout << a[i] << " "; } cout << endl; }while(next_permutation(a, a+n)); }
|
基于新数组的全排列
创建一个新数组b[],在 b[]上进行 a[]的全排列,这里就是最原始的Dfs了;
v[]标记已经排列过的元素,避免再次排列,ans记录全排列次数
————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void dfs(int k){ if(k == n){ for(int i = 0; i < n; ++i){ cout << b[i] << " "; } cout << endl; ans++; return; } for(int i = 0; i < n; ++i){ if(!v[i]){ v[i] = 1; b[k] = a[i]; dfs(k+1); v[i] = 0; } } }
|
这样的Dfs不能实现去重,如[1 2 3 4 4]会在全排列中出现两次;
激动人心时刻来临!去重只需添加一行代码,即在上面注释位置添加:
if(i>0 && a[i]==a[i-1] && !v[i-1]) continue;
原数组上进行的全排列
方法很巧妙,只在数组a[]上通过交换位置实现的全排列
————————————————————————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| void dfs(int k){ if(k == n){ for(int i = 0; i < n; ++i){ cout << a[i] << " "; } cout << endl; ans++; } for(int i = k; i < n; ++i){ { int t = a[i]; a[i] = a[k]; a[k] = t; } dfs(k+1); { int t = a[i]; a[i] = a[k]; a[k] = t; } } }
|
没有新数组的创建,显然这样不能实现去重,所以要去重还要借助set
反正咱也不闲麻烦,最后对a[]进行一下去重吧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| set<string> s; void to_string(string &str){ for(int i = 0; i < 12; ++i){ str.insert(str.end(), a[i]+'0'); } } bool isExist(){ string str; to_string(str); if(s.find(str) == s.end()){ s.insert(str); return false; } return true; }
|