全排列问题
全排列问题定义:
一般地,从n个不同元素中取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列(Sequence,Arrangement, Permutation)。
n个不同元素全部取出的一个排列,叫做n个不同元素的一个全排列。这是在排列数公式中,m=n,即有:
Ann=n·(n-1)·(n-2)·…·3·2·1
举例:
输入:
1 2 3
输出: 1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 3 1 2
设R={r1,r2,r3...rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为Perm(X)。(ri)Perm(X)表示在全排列Perm(X)的每一个排列前加上前缀ri得到的排列。R的全排列可归纳定义如下:
当 n = 1时,Perm(R) = (r) ,其中r是集合R中唯一的元素;
当 n > 1时,Perm(R)由(ri)Perm(R1),(r2)Perm(R2)....(rn)Perm(Rn)构成。
依次递归定义,可设计产生Perm(R)的递归算法如下
void swap(int &a,int &b) { int c; c=a; a=b; b=c; } void Perm(int a[],int k,int m) {//产生a[k:m]的所有排列 if(k==m) { //只剩下1个元素 for(int i=0; i<=k; i++) cout<<a[i]<<" "; cout<<endl; } else//还有多个元素待排列,递归产生排列。 { for(int i=k; i<=m; i++) { swap(a[i],a[k]); //替换 Perm(a,k+1,m); swap(a[i],a[k]);//恢复 } } }
算法Perm(list,k,m) 递归地产生所有前缀是list[0;k-1],且后缀是list[k;m]的全排列的所有排列。函数调用Perm(list,0,n-1),则产生list[0:n-1]的全排列。
在一般情况下,k<m.算法将list[k:m]中的每一个元素分别与list[k]中的元素交换。然后递归地计算list[k+1:m]的全排列,并将计算结果作为list[0:k]的后缀。算法中swap是调用于交换两个变量值的函数。