如何计算第n个排列(或告诉给定排列的字典顺序)?

时间:2015-03-24 15:24:52

标签: algorithm permutation combinatorics

这个问题有两个部分,但是因为我正在尝试与Prolog实现竞争,解决一个可能会立即导致另一个的解决方案。

  1. 给定整数列表{1,2,...,N}的排列,如何判断词典排序中该排列的索引是什么?
  2. 如果给出了k,我该如何计算k - 数字排列{1,2...,N}
  3. 我正在寻找一种能够比仅仅next permutation函数k次迭代更好的算法。 Afaik应该可以直接计算这两者。

    到目前为止我想到的是,通过查看左边的数字,我可以知道在特定索引处的每个数字之前有多少排列,然后以某种方式组合这些,但我不确定这是否导致正确的解决方案。

3 个答案:

答案 0 :(得分:4)

考虑有多少排列以数字1开头,有多少排列以数字2开头,依此类推。假设n = 5,那么24个排列从1开始,24开始于2,依此类推。如果你正在寻找排列说k = 53,那么有48个排列从1或2开始,所以#53是从3开始排列的第五个。

在从3开始的排列中,每个都以31,32,34或35开始。所以你正在寻找从(3,1)开始的第五个排列。有两个排列,每个排列从312,314和315开始。所以你正在寻找从315开始的两个排列中的第一个。这是31524.

应该很容易将其转换为代码。

答案 1 :(得分:3)

我将简要介绍每种方案的解决方案:

  

给定整数列表{1,2,...,N}的排列,如何判断词典排序中该排列的索引是什么?

要做到这一点,问问自己有多少排列以1开头?有(N - 1)!。现在,让我们举个例子:

3 1 2

1 2 31开始有多少2个排列? 2*2!。这个必须在那之后,所以它的索引至少是2*2! = 4。现在检查下一个元素。 1 20开头的排列数是多少?没有。你完成了,索引是4。如果要使用基于1的索引,可以添加1

  

给定数k,如何计算数字的第k个排列{1,2 ...,N}?

鉴于4,我们如何获得3 1 2?我们必须找到每个元素。

第一个位置我们能得到什么?如果我们有1,则最大索引可以是2! - 1 = 1(我使用的是从零开始的索引)。如果我们有2,则最高可以是2*2! - 1 = 3。如果我们有3,则最高可以是5。所以我们必须3

3

现在,我们已经将问题缩小为找到4 - 2*2! = 0 1 2的{​​{1}}排列,即1 2(您可以如上所述递归推理)。

答案 2 :(得分:3)

您还可以查看阶乘数系统,尤其是关于permutations的部分。对于给定的数字k,首先应该找到它的阶乘表示,然后很容易给出所需的排列(实际上,(k+1) - st置换)。

k=5和数字{1,2,3}的示例:

5 = 2 * 2! + 1 * 1! + 0 * 0! =(210)_!

所以5的阶乘表示是210.现在让我们将该表示映射到置换中。我们从有序列表(1,2,3)开始。我们的阶乘表示中最左边的数字是2,所以我们在索引2处查找列表中的元素,即3(列表为零索引)。现在我们留下列表(1,2)并继续该过程。在删除2后,我们的阶乘表示中最左边的数字是1,所以我们得到索引1处的元素,即2。最后,我们留下1,所以(k+1) - st(第6)置换{1,2,3}的{3,2,1}。

即使需要一些时间来理解它,它仍然是非常有效的算法并且编程简单。反向映射类似。