全排列
全排列
暴力枚举,每次在数组中选一个数,能则继续选下一个。否则另找一个数。
#include<iostream> /// 排列 #include<cstdio> #include<cstring> using namespace std; /** 1~n的全排列 */ void next(int n,int* a,int cur) /// 1~n的全排列 cur 要填充的位置 { if(cur==n){ for(int i=0;i<n;i++)printf("%d ",a[i]); printf("\n"); } else for(int i=1;i<=n;i++){ //从n个数中找一个 填补a[cur] int ok=1; for(int j=0;j<cur;j++) if(a[j]==i) ok=0; // i 已经在a[0]~a[cur-1] 中出现 if(ok){ a[cur]=i; next(n,a,cur+1); } } } /** 数组b[]的全排列 b[]中的元素要互不同样 */ /// way one void next_b_1(int n,int*a,int*b,int cur) /// b[]中的数互不同样 b[]的全排列 { if(cur==n){ for(int i=0;i<n;i++)printf("%d ",a[i]); printf("\n"); } else{ for(int i=0;i<n;i++){ int ok=1; for(int j=0;j<cur;j++) if(a[j]==b[i]) ok=0; if(ok){ a[cur]=b[i]; next_b_1(n,a,b,cur+1); } } } } /// way two int v[1000]={0}; void next_b_2(int n,int*a,int*b,int cur) /// b[]中的数互不同样 b[]的全排列 { if(cur==n){ for(int i=0;i<n;i++)printf("%d ",a[i]); printf("\n"); } else{ for(int i=0;i<n;i++){ if(!v[i]){ v[i]=1; /// 标记走过没有 a[cur]=b[i]; next_b_2(n,a,b,cur+1); v[i]=0; } } } } /** 数组b[]的全排列 b[]中的元素同意同样 只是b[]要有序 */ void next_c(int n,int*a,int*b,int cur) /// b[]中的数能够同样 注意 b[]要有序 需先排序 { if(cur==n){ for(int i=0;i<n;i++)printf("%d ",a[i]); printf("\n"); } else{ for(int i=0;i<n;i++) if(!i||b[i]!=b[i-1])/// 确保多个同样的数 仅仅递归一个就可以 { int c1=0,c2=0; for(int j=0;j<cur;j++) if(a[j]==b[i]) c1++; for(int j=0;j<n;j++) if(b[j]==b[i]) c2++; if(c1<c2){ a[cur]=b[i]; next_c(n,a,b,cur+1); } } } } int main() { //freopen("out1.txt","w",stdout); int a[100]={0}; //next(5,a,0); int b[]={5,1,7,3,8}; int n=5; //next_b_1(n,a,b,0); next_b_2(n,a,b,0); int b_1[]={1,2,2,3}; n=4; //next_c(n,a,b_1,0); int b_2[]={2,1,1,1}; n=4; //next_c(n,a,b_2,0); return 0; }