python排列组合算法,三个数字排序python

  python排列组合算法,三个数字排序python

  1.安排整个安排n!

  1.1递归法设置一组数p={r1,r2,r3,…,rn},所有数排列为perm(p),PN=p—{ rn }。那么perm (p)=r1perm (p1),r2perm (p2),r3perm (p3),…,rnperm (pn)。当n=1时,Perm(p}=r1。

  例如,找出{1,2,3,4,5}的完全排列

  1.先看最后两个数字4,5。它们的全排列是4 ^ 5和5 ^ 4,即5从4开始的全排列和4从5开始的全排列。

  因为一个数的完全置换是它本身,所以得到上面的结果。

  2.看最后三个数字3,4,5。它们的总排列是3 4 5,3 5 4,4 3 5,4 5 3,5 3 4和5 4 3组。

  即3和4,5完全排列的组合,4和3,5的组合,5和3,4的组合。

  #使用命名空间std包含iostreamusingVoidperm (int start,int end,int A[]){//得到全置换的一种情况,输出结果为if(start==end){ for(int I=0;我结束;I)cout a[I]“”;cout endl返回;} for(int I=start;我结束;i ) { swap(a[start],a[I]);//交换Perm(start 1,end,a);//全置换swap(a[i],a[start])分解成子问题a[start 1,end-1];//回溯}}int main() {int i,n,a[10];while (cin n,n){ for(I=0;I n;I){ a[I]=I ^ 1;} Perm(0,n,a);}返回0;} 2.组合C(n,K),从n的个数中取K的任意个数。

  2.1递归法其实就是在N个数中标记K个数,然后输出这个K个数的过程。使用一个访问过的数组来记录相应的下标数字是否被选中。

  #使用命名空间std包含iostreamusingVoidfs (int pos,int CNT,int n,int k,int a [],bool visited[]){//已经标记了k的个数,输出结果为if(CNT==k){ for(int I=0;I n;i ) if(已访问[I])cout a[I]“”;cout endl返回;}//处理到最后一个数字,直接返回if(pos==n)return;//如果(!visited[pos]){//Check a[pos]visited[pos]=true;//处理子串a[pos 1,n-1]中取出k-1个数的子问题dfs(pos 1,cnt 1,n,k,a,visited);//回溯访问过的[pos]=false;}//处理取出子串a[pos 1,n-1]中k个数的问题dfs(pos 1,cnt,n,k,a,visited);}int main() { int i,n,k;while (cin n k,n k){ int * a=new int[n];bool * visited=new bool[n];for(I=0;I n;I){ a[I]=I ^ 1;visited[I]=false;} dfs(0,0,n,k,a,已访问);删除[]a;删除[]已访问;} getchar();返回0;} 2.2 01 转换方法这个程序的思路是打开一个数组,数组的下标表示从1到n的数,数组元素的值为1表示选择了它所代表的数,0表示没有选择。

  首先将数组的前n个元素设置为1,表示第一个组合是第n个数。

  然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合并将其改为“01”组合,将其左边的所有“1”移动到数组的最左端。

  当第一个“1”移动到数组的第n-m个位置,即所有N个“1”都移动到最右边时,得到最后一个组合。

  例如,找出5选3的组合:

  1 1 1 0 0 //1,2,3

  1 1 0 1 0 //1,2,4

  1 0 1 1 0 //1,3,4

  0 1 1 1 0 //2,3,4

  1 1 0 0 1 //1,2,5

  1 0 1 0 1 //1,3,5

  0 1 1 0 1 //2,3,5

  1 0 0 1 1 //1,4,5

  0 1 0 1 1 //2,4,5

  0 0 1 1 1 //3,4,5

  #使用命名空间标准包含iostreamusing//输出结果void printRes(int* a,bool* index,int n){ for(int I=0;在;I){ if(index[I]){ cout a[I] ;} } cout endl}//检查最后k个位置是否已全变成0bool hasDone(bool* index,int n,int k){ for(int I=n-1;I=n-k;我- ) {如果(!index[i]) {返回false} }返回true}void Comb(int* a,int n,int k){ bool * index=new bool[n]();//选中前k个位置for(int I=0;我k;I){ index[I]=true;} printRes(a,index,n);而(!hasDone(index,n,k)) { //从左到右扫描数组for(int I=0;I n-1;i ) { //找到第一个"10"组合将其变成01组合if (index[i]!index[I 1]){ index[I]=false;index[I 1]=true;//将01组合左边的一移到最左边int count=0;for(int j=0;j I;j){ if(index[j]){ index[j]=false;index[count]=true;} } printRes(a,index,n);打破;} } }删除[]索引;}int main(){ int n,k;while(cinnk){ int * a=new int[n]();for(int I=0;I n;I){ a[I]=I ^ 1;} Comb(a,n,k);删除[]a;}返回0;}

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: