• 再议“生成全排列算法”


      看了“白话算法(7) 生成全排列的几种思路(一)”和“白话算法(7) 生成全排列的几种思路(二) 康托展开”。在此,将以前本人推导的全排列算法介绍一下,和广大的网友交流一下。

      以例子说明,用0、1、2、3,四个数组成全排列。

      首先可以知道,这四个数组成的全排列一共有4!=24个。那么给这24个全排列编号,分别为0、1、2……23。再给定一个算法,通过编号计算出一个全排列。本文的目的就是找到这样的算法。

      把所有的全排列列举出来可以发现,0在末位的有6个,1在末位的有6个,等等。

      观察0在末位的六个,分别是

      1、2、3、0

      1、3、2、0

      2、1、3、0

      2、3、1、0

      3、1、2、0

      3、2、1、0

      可以看出这6个全排列,除了末位是0外,前面三个数正好是1、2、3的全排列

      再观察1在末位的六个,分别是

      0、2、3、1

      0、3、2、1

      2、0、3、1

      2、3、0、1

      3、0、2、1

      3、2、0、1

      也可以看出这6个全排列,除了末位是1外,前面三个数正好是0、2、3的全排列

      类似的,末位是2和3的6个全排列,除了末位是一样的以外,前面三个数正好是剩下的三个数的全排列。

      

      于是该问题就可以用下面的步骤来解决。

      1、根据编号确定末位数字

      2、确定末位数字后,获得剩余的数字

      3、对编号适当的处理,得到新的编号

      4、问题演化成除了末位数字后,用新的编号和剩余的数字,计算剩余数字的全排列。

      再用一个具体的例子来说明。比方说,用编号13来计算0、1、2、3的一个全排列。

      1、先给这4个数字排好序。是0、1、2、3

      2、计算[13/3!]+1=3,表示末位数是第3个数。注:[X]表示取X的整数部分。

      3、把第3个数和第4个数(未排的最后1个数)交换。此时,数字的顺序是0、1、3、2。蓝色的表示已经排好。

      4、新的编号为13 mod 3!=1

      5、计算[1/2!]+1=1,表示末位数是第1个数。

      6、把第1个数和第3个数(未排的最后1个数)交换。此时,数字的顺序是3、1、0、2。蓝色的表示已经排好。

      7、新的编号为1 mod 2!=1

      8、计算[1/1!]+1=2,表示末位数是第2个数。

      9、把第2个数和第2个数(未排的最后1个数)交换。此时,数字的顺序是3、1、0、2。蓝色的表示已经排好。

      10、因为只剩下一个数,所以编号13对应的全排列就是3、1、0、2

      其他的编号计算方法和此一样。

      后面的这个表格就是按照上面的算法得到所有的编号和全排列的关系

    A(0) A(1) A(2) A(3) 编号
    1 2 3 0 0
    2 1 3 0 1
    2 3 1 0 2
    3 2 1 0 3
    1 3 2 0 4
    3 1 2 0 5
    3 2 0 1 6
    2 3 0 1 7
    2 0 3 1 8
    0 2 3 1 9
    3 0 2 1 10
    0 3 2 1 11
    1 3 0 2 12
    3 1 0 2 13
    3 0 1 2 14
    0 3 1 2 15
    1 0 3 2 16
    0 1 3 2 17
    1 2 0 3 18
    2 1 0 3 19
    2 0 1 3 20
    0 2 1 3 21
    1 0 2 3 22
    0 1 2 3 23

      

      通过这样的算法,通过指定的编号就能算出一个全排列。

      如果要遍历所有的全排列,则只要遍历编号就能完成。

      如果要随机获得一个全排列,则随机生成一个编号,再计算出全排列就可以了。

      具体的代码在我之前的文章“遍历排列的实现——VB2005”中,这里就不重复贴出了。

  • 相关阅读:
    2018/12/08 L1-043 阅览室 Java
    2018/12/08 L1-042 日期格式化 Java
    breeze源码阅读心得
    Spark ML源码分析之四 树
    Spark ML源码分析之三 分类器
    Spark ML源码分析之二 从单机到分布式
    Spark ML源码分析之一 设计框架解读
    Adaboost的意义
    RBM如何训练?
    ChromeTimeline
  • 原文地址:https://www.cnblogs.com/grenet/p/2032812.html
Copyright © 2020-2023  润新知