@rebirth1120
2019-08-19T22:17:48.000000Z
字数 1271
阅读 770
组合数学
数学
虽然书上的标题写的是 "排列的生成算法", 但实际上貌似只有"全排列的生成算法".
本来想宇宙惯例先抄一段书, 结果发现书上写的及其啰嗦....还是我自己解释吧.
我们先重定义一下 "前缀" 和 "后缀".
在这里, 一个排列的 "后缀" 指的是该排列从后往前的一个连续上升序列,
"前缀" 则是这个排列删除它的后缀后的部分.
例如, 839647521 的后缀是 "7521", 前缀就是 "83964".
下面我就结合 839647521 这个排列来介绍一下我们的做法.
为什么是正确的呢, 我们来感性理解一下.
找比当前排列的序号(排名)更大的排列, 其实就是要用一个后面的数替换前面的一个比它小的数,
那么为了找到当前排列的下一个排列, 就要保证这个新排列的序号恰好比原排列的序号大 1 (废话),
那当前排列的后缀中的数显然是不能互相交换的, 不然新排列就会比原排列更小,
所以我们就要找到第一个能够与后缀中的数交换的数, 然后用后缀中尽可能小的数来替换它,
替换之后, 新序列已经比原序列大了, 那么为了保证它恰好比原序列大, 那么就将它的后缀排个序. 由于后缀是(从前往后)递减的, 所以我们只需将它翻转一下就行了.
这样, 我们就可以 口胡 理解这个方法的正确性了.
这个内容书上好像没有, 是我们老师上课时候讲的.
先上公式吧.
设当前排列为 , 定义 为 右边比 小的数的数量, 即 .
当前排列的序号为
还是结合例子来理解吧, 设当前序列为 83967521.
那么它的序号其实就是前缀先于 83967521 的排列个数+1, 我们记为 .
(PS : 这里的"前缀"不是前面重新定义的"前缀".)
那么我们一步一步来考虑, 先求前缀先于 8 的排列数,
那我们就保证排列的第一位小于 8, 剩下的八位就可以随便排了, 所以
继续, 求前缀先于 83 的排列数,
这时, 第一位就可以取 8 了, 我们只要保证第一位取 8 时第二位小于 3 就行了, 所以有
前缀为 839 时也一样, 只不过当第一位和第二位分别为 8 和 3 时, 由于 8 已经被选了, 第三位就不能取 8 了, 所以
最后得到
所以排列 839647521 的序号为 297192.