排列排序算法
我正在努力寻找有效的算法来计算排列的排名,反之亦然(给定排名的排列)。有人可以指点一下吗?
I'm struggling to find efficient algorithm for calculating the rank of a permutation, and vice versa (permutation for a given rank). Can someone give some pointers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
数组中有重复元素吗?
如果仅存在唯一元素,则以下递归将
X[m:n]
的排名计算为长度n-m+1
的排列>:两者都是
Rank 和
RankOfElement
是从零开始的(从 0 开始)。基本上,
Rank(排列) = Rank(从排列的第一个字母开始的第一个排列) + Rank(删除第一个字母的排列)
,例如对于字符串EDCBA
意味着排名(EDCBA) = 排名(EABCD) + 排名(DCBA)
。通过更改第一项,可以将其扩展到非唯一情况:
Do you have repeating elements in the array?
If there are only unique elements, the following recursion calculates the rank of
X[m:n]
as a permutation of lengthn-m+1
:Both
Rank
andRankOfElement
are zero-based (start at 0).Basically,
Rank(permutation) = Rank(first permutation starting with first letter of permutation) + Rank(permutation with first letter deleted)
, e.g. for stringEDCBA
that meansRank(EDCBA) = Rank(EABCD) + Rank(DCBA)
.This can be extended to non-unique cases by changing the first term:
编辑
我刚刚看到你的评论。不错的图形!你想要的是树遍历。
请注意排列中的每个位置在树中如何具有不同的级别?该树中从根到叶节点的每条路径都是可能的排列。
所以这意味着你的“等级”有一定的灵活性。你得定义它。只需将其设置为您想要对树进行的任何类型的遍历(中序、前序、后序、DFS、BFS)即可为您提供当您直接遍历每个叶节点时递增的叶节点编号。
因此,只需选择您认为对您的应用程序最自然或最方便的排列的遍历和排名即可。如果您无法选择,请询问 /dev/random 您应该使用哪种遍历。
END EDIT
首先,必须将其视为基本转换。每个排列都在一个点(它是排名)。想想二进制。计算 n 个字符上的 2 个字母表排列的有效算法是什么?只需分配排名即可得到排列。
同样的事情也适用于其他大小的字母。显然,如果您的位置具有不同大小的字母表,事情会更加复杂,但您仍然可以进行组合:
然后要从排名中获得排列,只需使用基数公式:我似乎记得:
如果您从组合和基数的角度考虑它,即使在更复杂的情况下,你也不会出错。只需采用您想要的任何排名并将其转换为适合您的字母表的基础即可。您可能对维基百科上的混合基数转换感兴趣
EDIT
I just saw your comment. Nice graphic! Right what you want is a tree traversal.
Notice how each position in your permutation has a distinct level in the tree? Every path from the root to a leaf node in that tree is a possible permutation.
So this means that your 'rank' has some flexibility. You get to define it. Just make it whatever type of traversal you want over the tree (inorder, preorder, postorder, DFS,BFS) to give you a numbering of leaf nodes incremented as you go straight through each leaf node.
So just choose the traversal and ranking of your permutations to be whatever you find most natural or convenient for your application. If you can't choose, ask /dev/random which traversal you should use.
END EDIT
Well first it has to be thought of like a base conversion. Every permutation is at a point (it's rank). Think of binary. What's an efficient algorithm for calculating a 2 alphabet permutation over n characters? Just assign the rank and you have the permutation.
The same thing works for alphabets of other size. Obviously things are more complicated if your positions have different size alphabets, but you can still do the combinatorics :
Then to get permutation from rank just use a radix formula : I seem to remember:
If you think about it from this combinatorical and radix perspective, you can't go wrong, even in more complex cases. Just take whatever rank you want and convert it into the base that's appropriate for your alphabet. You may be interested in Mixed Radix Conversion on Wikipedia, here