【发布时间】:2012-02-19 01:02:31
【问题描述】:
我正在努力寻找有效的算法来计算排列的等级,反之亦然(给定等级的排列)。有人可以指点一下吗?
【问题讨论】:
-
这里stackoverflow.com/a/8958309/312172 我做了一个图形,说明问题,并以一种方式给出解决方案。如果您查看右侧的
related问题列表,您会发现许多重复项。
我正在努力寻找有效的算法来计算排列的等级,反之亦然(给定等级的排列)。有人可以指点一下吗?
【问题讨论】:
related 问题列表,您会发现许多重复项。
数组中有重复的元素吗?
如果只有唯一元素,则以下递归将X[m:n] 的排名计算为长度n-m+1 的排列:
Rank(X, m:n) = RankOfElement(X[m], X[m:n]) * Factorial(n - m) + Rank(X, (m+1):n)
Rank 和 RankOfElement 都是从零开始的(从 0 开始)。
基本上,Rank(permutation) = Rank(first permutation starting with first letter of permutation) + Rank(permutation with first letter deleted),例如对于字符串EDCBA,表示Rank(EDCBA) = Rank(EABCD) + Rank(DCBA)。
这可以通过更改第一项扩展到非唯一情况:
Rank(X, m:n) = Rank(X, (m+1):n) + ∑ over (y ∈ X[m:n], y
【讨论】:
编辑
我刚刚看到你的评论。漂亮的图形!你想要的是树遍历。
注意排列中的每个位置如何在树中具有不同的级别?从根到该树中叶节点的每条路径都是可能的排列。
所以这意味着您的“等级”具有一定的灵活性。你要定义它。只需在树上进行任何类型的遍历(顺序、前序、后序、DFS、BFS),即可在您直接通过每个叶节点时为您提供叶节点的编号。
因此,只需选择您的排列的遍历和排名,使其成为您认为对您的应用程序最自然或最方便的任何内容。如果无法选择,请询问 /dev/random 应该使用哪种遍历。
结束编辑
首先必须将其视为基本转换。每个排列都在一个点(它的等级)。想想二进制。计算 n 个字符的 2 个字母排列的有效算法是什么?只需分配等级,您就有排列。
同样的事情也适用于其他大小的字母。显然,如果你的职位有不同大小的字母,事情会更复杂,但你仍然可以做组合:
total possible = pi(|a|_i) for all i in positions
|a|_i alphabet size at position i
and assuming all |a|_i are equal to b you have
rank of permutation = sigma(b**i * a_i)
a_i is actual alphabet character chosen at position i.
So over the 5 alphabet (ABCDE)
The rank of AAAAA = 0 (or 1)
The rank of EEEED = 5**6 - 2
然后要从排名中获得排列,只需使用基数公式:我似乎记得:
a_i = (P % b**(i+1) - P & (b**i))/(b**i)
如果您从组合和基数的角度考虑它,即使在更复杂的情况下,您也不会出错。只需采用您想要的任何等级并将其转换为适合您的字母表的基础。你可能对Mixed Radix Conversion on Wikipedia, here感兴趣
【讨论】: