这个问题有两个部分,但是因为我正在尝试与Prolog实现竞争,解决一个可能会立即导致另一个的解决方案。
{1,2,...,N}
的排列,如何判断词典排序中该排列的索引是什么?k
,我该如何计算k
- 数字排列{1,2...,N}
?我正在寻找一种能够比仅仅next permutation
函数k
次迭代更好的算法。 Afaik应该可以直接计算这两者。
到目前为止我想到的是,通过查看左边的数字,我可以知道在特定索引处的每个数字之前有多少排列,然后以某种方式组合这些,但我不确定这是否导致正确的解决方案。
答案 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 3
或1
开始有多少2
个排列? 2*2!
。这个必须在那之后,所以它的索引至少是2*2! = 4
。现在检查下一个元素。 1 2
以0
开头的排列数是多少?没有。你完成了,索引是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}。
即使需要一些时间来理解它,它仍然是非常有效的算法并且编程简单。反向映射类似。