一、全排列的定义
当从n个不同元素中任取m(m≤n)个元素,按照某特定的顺序排列起来,则将这个m个元素叫做一个排列。当m=n时所有的排列情况叫全排列。
比如1,2,3,4四个元素的全排列:
1234,1243,1324,1342,1423,1432
2134,2143,2314,2341,2413,2431
3124,3142,3214,3241,3412,3421
4123,4132,4213,4231,4312,4321
由此可知全排列的公式:f(n)=n!(定义0!=1)
二、常见的几种全排列生成算法
2.1递归类算法
2.1.1递归算法
- 若P是表示n个元素的的一个排列,Pj表示没有元素j的排列,(j) Pj表示在排列Pj前加上前缀j的排列,则n个元素的排列定义为:
a) 若n=1,则排列P只有一个元素j。
b) 若n>1,则排列P由排列(j) Pj构成(j=1、2、…、n-1)。
-
由此得出如果已生成了i-1个元素的排列,则i个元素的排列可以在每个i-1个元素的排列Pj前添加元素j而生成。
-
例如对于4个元素而言,P1是2 3 4,2 4 3,3 2 4,3 4 2,4 2 3,4 3 2,然后在每个排列前加上1即生成1开头的4个元素的新排列,按同样方法即可生成其他剩余的所有排列。
2.1.2回溯法
回溯法是通过构造一颗生成树来表示全排列,以3个元素为例;
-
树的根节点的数据可以取值1、2、3。
-
初始状态是(0,0,0),“0”则表示它尚未取值。树的子节点(第一个元素)同样取可能值1、2、3。
-
在树的叶子节点(第二个元素)以同样的方法取值,如此反复进行,当出现新结点的3个数据全非零,那就找到了一种全排列方案。所有可能的方案都进行完成后,则得到了所有的全排列。
2.1.3循环移位法
-
若已经有了n-1个元素的排列,则在每个排列后添加元素n使之成为n个元素的排列,再将每个排列循环左移或者是右移,每移动一次就产生一个新的排列。
-
例如3个元素的排列中有这样两个排列是1 2 3和2 1 3,在它们后加上4则成为新排列1 2 3 4和2 1 3 4然后将它们循环右移,于是可以重新生成排列4 1 2 3、3 4 1 2、2 3 4 1和4 2 1 3、3 4 2 1、1 3 4 2。这样既可由3个元素所有的排列生成所有的4个元素的排列。
2.2字典序法
假设P是1~n的一个全排列:P= P1…Pi-1PiPi+1…Pj-1PjPj+1…Pn
-
首先将排列的所有数字从左端开始标上序号i(i=1,2, …,n),再从排列的右端找出第一个比右边所有数字小的数字序号i,所以i是所有小于Pk+1的数字中序号最大者,即i=Max{k/ Pk< Pk+1}
-
其次找出Pi右边比其大的所有数字,再从这些数中找出最小的数字Pj,由于序号是从左端开始,所以j是所有大于Pi的数字中序号最大者,即j=Max{k|Pk>Pi}。
-
然后将Pi,Pj相互交换,再将Pi+1… Pj-1PjPj+1… Pn倒转得到一个新的排列:Pn=P1…Pi-1PjPn…Pj+1PiPj-1…Pi+1,这就是P的下一个排列。
例如754938621是数字1~9的一个排列;有字典序法得出下一个排列具体步骤如下:
a) 从右端向左边开始找出第一个比右边数字小的数字是3。
b) 其次找出3以后的比它大的数字中最小的数字6。
c) 将3与6交换得出754968321。
d) 然后将8321倒转得出 754961238。
e) 所以754938621的下一个排列是754961238。
2.3递增进位制数法
递增进位制数法中中介数是计算排列的中间环节,需要用它来通过一个已知的排列求出另外一个排列。
-
如果用 Lj表示排列P1P2…Pj…Pn中元素Pj的右边比其小的数的个数,则排列的中介数就是指与其相互对应的排列L1L2 … Lj…Ln-1。
-
如排列754938621的中介数是64352321,这些数字分别表示7、5、4、9、3、8、6、2的右边比其小的数的个数。
-
某排列的下一个排列,其中介数是原排列中介数加1,且如果中介数的末位Ln-1+1=2,则要向前进位;如果Lj+1=n-j+1,则要进位。
-
如排列754938621的中介数是64352321,则下一个排列的中介数是64352321+1=64353000(因为Ln-1+1=1+1=2,所以向前进位;Lj+1=2+1=3=9-7+1 =n-j+1,所以又发生进位;Lj+1=3+1=4=9-6+1 =n-j+1,所以又发生进位,所以下一个中介数是64353000)。
-
得到中介数之后,可根据它还原相对应的排列。由于中介数L1 … Lj… Ln-1中各数字依次表示排列中的数字n、n-1、…、2在排列中距右端的空位数,所以按照L1 …Lj…Ln-1的值,按右往左的顺序确定n、n-1、…、2的位置,且依次放置在排列里。
-
使得j放在从右端开始的Lj+1位;然而若此位已经放有数字,则该位置不算在内,且最后一个空位放1。
-
则从64353000可得到排列619587234,它就是754938621的后一个排列。由于9是最先放置的,L1=6,9放在从右端起第7位,空出6个空位;然后是放8,L2=4,8应放在从右端起第5位,依次计算下去即可得出余下所有的排列。
2.4递减进位制数法
递减进位制数法同递增进位制数法方法同理,只是需要将递增进位制数法翻转过来即可得到。
- 754938621的中介数是64352321(L1L2…Ln-1),倒转成为12325346
(Ln-1…L2L1),这就是递减进位制数的中介数:Li(i=n-1,n-2,…,2)位逢i向Li-1位进1。
-
给出一个排列,其下一个排列的中介数的求法仍然同递增进位制数法相同,仍然是原排列的中介数加1得到下一个排列的中介数。
-
如排列754938621的中介数为12325346,则下一个排列的中介数为12325346+1=12325347,用同递增进位制数相同的方法得到下一个排列为694387521。
-
在递减进位制数中,一种方法不需要计算中介数,就可以直接从一个排列求出下一个排列:
a) 若有Pk=n且k<n,则Pk与左边的数字交换
b) 若有Pn=n,则首先找出一个连续递减的序列n、n-1、…、k,将这个序列从排列左端删除,再以相反顺序加在排列右端,然后将k-1与左边的数字交换。
c) 如求排列754938621(Pn Pn-1 …Pk… P1)的下一个排列,则先找到最大数字n=9,即P6=9,然后将9与4交换,则得到下一个排列是759538621。
d) 如求排列984657321的下一个排列,由于P9 = 9在最左边,且P8=8,则有一个连续的递减数列98,所以将98从小到大(即89)排于最右端465732189,再将k-1位即7与其左方数字对调得到467532189是排列984657321的下一个排列。
2.5邻位交换法
邻位对换法中排列的下一个排列是此排列的某相邻两位元素相互交换而得出来的。具体方法的步骤如下:
- 以5个元素的排列为例,将最后的元素5逐次与前面的元素交换,可以生成5个新排列:
1 2 3 4 5,1 2 3 5 4, 1 2 5 3 4, 1 5 2 3 4,5 1 2 3 4
- 其次是将最后一个排列末尾的2个元素相互交换;然后再逐次将排头的5与其后的各个元素相互交换,继而又生成了5个全新的排列:
5 1 2 4 3, 1 5 2 4 3, 1 2 5 4 3, 1 2 4 5 3, 1 2 4 3 5
- 再将最后一个排列前端的2个元素相互交换;然后将再将5从后往前移:
2 1 4 3 5, 2 1 4 5 3, 2 1 5 4 3, 2 5 1 4 3, 5 2 1 4 3
如此反复循环既可求出5个元素全部的排列。
2.6 元素增值法
元素增值法又叫做n进制法:
-
从原始排列P=P1P2…Pn开始,第n位加n-1,如果该位的值超过n,则将它除以n,用余数取代该位,并进位,即将第n-1位加1)。
-
再按同样方法处理n-1位,n-2位,…,直至不再发生进位为止,处理完一个排列就产生了一个新的排列。
-
将其中包含有相同元素的排列去掉。
-
当第一个元素的值>n事,则方法结束。
以4个元素的排列为例:原始排列是1 2 3 4,从它开始,第4个元素是4,4+3=7>4,则7 Mod 4=3,且向前进1为;第3个元素是3,则3+1=4,没有大于4,则不用进位;第2个元素与第1个元素不变,则生成新的排列是1 2 4 3。以此类推,即可得到4个元素的全部的排列。