具有重复项的排列的排名和取消排名
我正在阅读有关排列的内容,并且对排名/取消排名方法感兴趣。
来自一篇论文的摘要:
n 个符号的排列的排序函数分配一个唯一的 [0, n! 范围内的整数- 1] 到 n! 个中的每一个!排列。相应的 取消排名函数是逆函数:给定 0 到 n 之间的整数! - 1、 函数的值是具有该秩的排列。
我使用 next_permutation 在 C++ 中创建了排名和取消排名函数。但这对于n>8来说是不切实际的。我正在寻找一种更快的方法,并且 factoradics 似乎很受欢迎。 但我不确定这是否也适用于重复项。那么,对重复的排列进行排名/取消排名的好方法是什么?
I'm reading about permutations and I'm interested in ranking/unranking methods.
From the abstract of a paper:
A ranking function for the permutations on n symbols assigns a unique
integer in the range [0, n! - 1] to each of the n! permutations. The corresponding
unranking function is the inverse: given an integer between 0 and n! - 1, the
value of the function is the permutation having this rank.
I made a ranking and an unranking function in C++ using next_permutation. But this isn't practical for n>8. I'm looking for a faster method and factoradics seem to be quite popular.
But I'm not sure if this also works with duplicates. So what would be a good way to rank/unrank permutations with duplicates?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我将在这个答案中涵盖你的问题的一半 - “取消排名”。目标是有效地找到有序字符串 [abcd...] 的字典顺序“K”排列。
为此,我们需要了解阶乘数系统(factoradics)。阶乘数字系统使用阶乘值而不是数字的幂(二进制使用 2 的幂,十进制使用 10 的幂)来表示位值(或基数)。
位值(基数)为 –
第零位的数字始终为 0。第一位的数字(基数 = 1!)可以是 0 或 1。第二位的数字(基数为 2!)可以是是 0,1 或 2 等等。一般来说,第n位数字可以取0-n之间的任意值。
前几个数字表示为因数 - 字符串
的第 n 个字典排列与其因数表示之间存在直接关系。
例如,以下是字符串“abcd”的排列。
如果仔细观察,我们可以在这里看到一种模式。第一个字母在每 6 次(3!)次排列后发生变化。第二个字母在 2(2!) 排列后发生变化。第三个字母在每(1!)次排列后改变,第四个字母在每(0!)次排列后改变。我们可以利用这个关系直接求出第n个排列。
一旦我们用因子表示法表示 n,我们就会考虑其中的每个数字,并将给定字符串中的一个字符添加到输出中。如果我们需要找到'abcd'的第14个排列。 14 因子 -> 2100.
从第一个数字开始->2,字符串为'abcd'。假设索引从 0 开始,从字符串中取出位置 2 处的元素并将其添加到输出中。
下一个数字 -> 1.字符串现在是“abd”。再次,选取位置 1 处的字符并将其添加到输出中。
下一个数字 -> 0. 字符串是“ad”。将位置 1 处的字符添加到输出。
下一个数字 -> 0. 字符串是“d”。将位置 0 处的字符添加到输出。
输出字符串
CBAD ''
2100
要将给定数转换为阶乘数制,请依次将该数除以 1、2、3、4、5 等,直到商变为零。每个步骤的提醒形成因子表示。
例如,要将 349 转换为因数,
349 的因数表示为 242010。
I will cover one half of your question in this answer - 'unranking'. The goal is to find the lexicographically 'K'th permutation of an ordered string [abcd...] efficiently.
We need to understand Factorial Number System (factoradics) for this. A factorial number system uses factorial values instead of powers of numbers (binary system uses powers of 2, decimal uses powers of 10) to denote place-values (or base).
The place values (base) are –
The digit in the zeroth place is always 0. The digit in the first place (with base = 1!) can be 0 or 1. The digit in the second place (with base 2!) can be 0,1 or 2 and so on. Generally speaking, the digit at nth place can take any value between 0-n.
First few numbers represented as factoradics-
There is a direct relationship between n-th lexicographical permutation of a string and its factoradic representation.
For example, here are the permutations of the string “abcd”.
We can see a pattern here, if observed carefully. The first letter changes after every 6-th (3!) permutation. The second letter changes after 2(2!) permutation. The third letter changed after every (1!) permutation and the fourth letter changes after every (0!) permutation. We can use this relation to directly find the n-th permutation.
Once we represent n in factoradic representation, we consider each digit in it and add a character from the given string to the output. If we need to find the 14-th permutation of ‘abcd’. 14 in factoradics -> 2100.
Start with the first digit ->2, String is ‘abcd’. Assuming the index starts at 0, take the element at position 2, from the string and add it to the Output.
The next digit -> 1.String is now ‘abd’. Again, pluck the character at position 1 and add it to the Output.
Next digit -> 0. String is ‘ad’. Add the character at position 1 to the Output.
Next digit -> 0. String is ‘d’. Add the character at position 0 to the Output.
Output String
cbad ''
2100
To convert a given number to Factorial Number System,successively divide the number by 1,2,3,4,5 and so on until the quotient becomes zero. The reminders at each step forms the factoradic representation.
For eg, to convert 349 to factoradic,
Factoradic representation of 349 is 242010.
一种方法是按一组特定的相同数字对索引的选择进行排序和取消排序,例如,
One way is to rank and unrank the choice of indices by a particular group of equal numbers, e.g.,
对于大型 ns,您需要任意精度库,例如 GMP。
这是我之前用 python 编写的取消排名函数的帖子,我认为它是可读的,几乎就像伪代码,评论中也有一些解释: 给定字典顺序的元素列表顺序(即['a','b','c','d']),找到第n个排列 - 求解的平均时间?
基于此你应该能够计算出排名函数,基本上是相同的逻辑;)
For large n-s you need arbitrary precision library like GMP.
this is my previous post for an unranking function written in python, I think it's readable, almost like a pseudocode, there is also some explanation in the comments: Given a list of elements in lexicographical order (i.e. ['a', 'b', 'c', 'd']), find the nth permutation - Average time to solve?
based on this you should be able to figure out the ranking function, it's basically the same logic ;)
Java,来自 https://github.com /timtiemens/permute/blob/master/src/main/java/permute/PermuteUtil.java (我的公共域代码,减去错误检查):
Java, from https://github.com/timtiemens/permute/blob/master/src/main/java/permute/PermuteUtil.java (my public domain code, minus the error checking):