全排列算法

我们先来明确一下全排列的概念:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。那么全排列算法的概念也就呼之欲出了。
全排列算法无论是在数学还是计算机领域都有很多的应用,是不可多得的优质算法之一,融会贯通到了许多其他的算法当中。本文我们就来介绍这几种全排列算法
一、字典序法
字典序法顾名思义就按照字典的顺序(a-z, 1-9),对给定的字符集中的字符规定了一个先后关系,在此基础上规定两个全排列的先后是从左到右逐个比较对应的字符的先后。
[例]字符集{1,2,3},较小的数字较先,
这样按字典序生成的全排列是:123,132,213,231,312,321。
[注意] 一个全排列可看做一个字符串,字符串可有前缀、后缀。
1)生成给定全排列的下一个排列 所谓一个的下一个就是这一个与下一个之间没有其他的。这就要求这一个与下一个有尽可能长的共同前缀,也即变化限制在尽可能短的后缀上。
[例]839647521是1–9的排列。
1—9的排列最前面的是123456789,最后面的是987654321,从右向左扫描若都是增的,就到987654321,也就没有下一个了。否则找出第一次出现下降的位置。
[序数公式]
有从 1 到 n 的连续的 n 个自然数,其全排列按照从小到大排列,次序从 0 到 n!-1 ,总共 n! 个。现有其全排列中的一组 “、、……”,其全排列次序为:

二、递增进位制数法
由排列求中介数 在字典序法中,中介数的各位是由排列数的位决定的.中介数位的下标与排列的位的下标一致。
在递增进位制数法中,中介数的各位是由排列中的数字决定的。即中介数中各位的下标与排列中的数字(2—n)一致。可看出n-1位的进位链。右端位逢2进1,右起第2位逢3进1,…,
这里对于一个全排列我们需要一个中介数,举个例子假设我们要求839647521按递增进位法的下100个全排列,这里我们生成其对应的中介数:9后面比9小的有6个数,8后面比8小的有7个数,7后面比7小的有3个数,6后面比6小的有4个数……mid[i]表示(n - i + 1)后面比(n - i + 1)小的数的个数,这里把(n - i + 1)换成a[i],经过整理i = n - a[i] + 1,mid[n - a[i] + 1]可以表示a[i]后面比a[i]小的数的个数,得到中介数mid = 673422210。
我们可以发现对于mid[i]最大为(n - i),因为比(n - i + 1)小的数只有(n - i)个。这样我们就可以发现中介数mid除去最后一个0就是一个递增进位制数(第i位的进位制是(n - i + 1),最后一位是二进制,因为一进制恒为0),这样我们让这个递增进位制数67342221加上100,就是67351311。
三、递减进位制数法
在递增进位制数法中,中介数的最低位是逢2进1,进位频繁,这是一个缺点。把递增进位制数翻转,就得到递减进位制数。 (anan-1…a2)↑→(a2a3…an-1an)↓
839647521→ (12224376)↓
(12224376)↓=1×3+2)×4+2)×5+2)×6+4)×7+3)×8+7)×9+6=340989
四、邻位对换法
递减进位制数法的中介数进位不频繁,求下一个排列在不进位的情况下很容易。这就启发我们,能不能设计一种算法,下一个排列总是上一个排列某相邻两位对换得到的,这也是邻位对换法的由来。
递减进位制数字的换位是单向的,从右向左,而邻位对换法的换位是双向的。 算法描述如下:
对1—n-1的每一个偶排列,n从右到左插入n个空档(包括两端),生成1—n的n个排列。
对1—n-1的每一个奇排列,n从左到右插入n个空档,生成1—n的n个排列。
对[2,n]的每个数字都是如此。
可以看到,相比于随机递推方法,中介数的引入带来了很大的优势。首先,全排列与中介数的一一映射关系使得全排列集合成为全序集,从而可以保证每个核的运算量是相等的,避免了并行计算中任务分配不均匀带来的短板效应。另一方面,每个核的任务均匀意味着可以提前知道每个核需要进行的递推次数,从而避免了每一次递推后都需要查看是否已经出现过的时间开销,大大提升了效率。实践证明,并行递推的算法加速比是最高的。
全排列算法本身的使用是有一定的局限性的,这也在一定程度上限制了它的发展,但由于其在排序方面的独特方式使得很多算法里都有它的身影。如果想深入了解全排列或者其他的优质算法可以观看本站的相关课程,对算法的讲解很是透彻。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值