【说人话的算法小课堂】按字典序升序枚举n个元素的所有全排列(算法步骤 + 正确性证明)

在这里插入图片描述

全排列

定义

从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个元素构成的子排列的字典序已经最大,

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值