全排列
定义
从n个元素中取出全部的n个进行排列,就得到全排列。
算法:按字典序升序枚举n个元素的所有全排列
设集合{a_1,a_2,…,a_n}的一个全排列为P=p_1,p_2,…,p_(j-1),p_j,p_(j+1),…,p_n。
【1】从排列的右端开始,找出第一个比右边数字小的数字的序号j。即:令
i=n-1,n-2,…
当第一次满足p_i<p_(i+1)时,停止,并记j=i。
如果没有找到符合条件的i,意味着整个排列的字典序已经最大,算法结束。
【2】在p_j右边的数字中,找出所有比p_j大的数字中最小的数字p_k,即
p_k=min〖{p_i |p_i>p_j, i=j+1,…,n}〗
k=i
如果存在多个符合条件的p_i,则记k为这些数中下标最大的那个数的下标。
【3】交换p_j,p_k。
【4】将排列最右端的递减区间倒转。
证明
下面证明:当原排列的字典序未达到最大时,按照上述算法构造出来的新排列(即下一个排列)一定比原排列的字典序更大,且字典序的增量最小。
把原排列划分成若干个子排列,每一段子排列要么递增,要么递减,要么既不递增也不递减。对于最右侧的一段(易知:该段的长度至少为2):
(1)若该段递增,则易证:执行一次此算法后,最右侧的两个数会交换位置,于是最右边的两个数构成了一个递减的子数列。转入情况(2)。
(2)若该段递减,则这段递减的子排列的字典序已经最大,也就是说不能在不改变这段子排列左侧的情况下,再把这段子排列的字典序变得更大。因此,若要构造下一个排列,必须要动用其它的元素。
设字典序已经最大的最右侧的那一段子排列的左侧有d个元素。在“需要增大前d个元素构成的排列的字典序”的条件下,为使整个排列的字典序的增量尽可能小,易得:前(d-1)个元素的顺序应当保持不变。
为了使新排列的字典序增大,又只能改变第d个到第n个元素的顺序,而第(d+1)到第n个元素构成的子排列的字典序已经最大,