2014-09-22 33 views
8

我正在考虑按字典顺序排列0,...,n-1的所有排列组合。我给出了两个等级,我和j,并要求找出将第i个置换应用于第j个置换所产生的排列的排列。将排列的排列索引到其他排列的排列中

对于n = 3所述的几个例子:

P(3)= [1,2,0],P(4)= [2,0,1],结果= [0,1,2 ],秩= 0

鉴于我= J = 4,我们得到[2,0,1]适用于本身是[1,2,0],秩= 3

什么我来到目前为止:我通过Lehmer代码将等级转换为它们各自的排列,计算所需的排列,并通过Lehmer代码转换回排名。

任何人都可以提出一种方法,从另外两个等级中获得想要的排列的排名,而不必实际计算排列吗?存储n! x n!数组不是一个选项。

-edit-请注意,如果某些其他命令会启用此功能,我不会使用字典顺序。

-edit-这里是n!由n!网格为n = 3 & 4,用于词典排名。第i行被索引到第j列以获取输出。请注意,n = 3网格与n = 4网格的左上角相同。

00|01|02|03|04|05| 
01|00|03|02|05|04| 
02|04|00|05|01|03| 
03|05|01|04|00|02| 
04|02|05|00|03|01| 
05|03|04|01|02|00| 

00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|15|16|17|18|19|20|21|22|23| 
01|00|03|02|05|04|07|06|09|08|11|10|13|12|15|14|17|16|19|18|21|20|23|22| 
02|04|00|05|01|03|08|10|06|11|07|09|14|16|12|17|13|15|20|22|18|23|19|21| 
03|05|01|04|00|02|09|11|07|10|06|08|15|17|13|16|12|14|21|23|19|22|18|20| 
04|02|05|00|03|01|10|08|11|06|09|07|16|14|17|12|15|13|22|20|23|18|21|19| 
05|03|04|01|02|00|11|09|10|07|08|06|17|15|16|13|14|12|23|21|22|19|20|18| 
06|07|12|13|18|19|00|01|14|15|20|21|02|03|08|09|22|23|04|05|10|11|16|17| 
07|06|13|12|19|18|01|00|15|14|21|20|03|02|09|08|23|22|05|04|11|10|17|16| 
08|10|14|16|20|22|02|04|12|17|18|23|00|05|06|11|19|21|01|03|07|09|13|15| 
09|11|15|17|21|23|03|05|13|16|19|22|01|04|07|10|18|20|00|02|06|08|12|14| 
10|08|16|14|22|20|04|02|17|12|23|18|05|00|11|06|21|19|03|01|09|07|15|13| 
11|09|17|15|23|21|05|03|16|13|22|19|04|01|10|07|20|18|02|00|08|06|14|12| 
12|18|06|19|07|13|14|20|00|21|01|15|08|22|02|23|03|09|10|16|04|17|05|11| 
13|19|07|18|06|12|15|21|01|20|00|14|09|23|03|22|02|08|11|17|05|16|04|10| 
14|20|08|22|10|16|12|18|02|23|04|17|06|19|00|21|05|11|07|13|01|15|03|09| 
15|21|09|23|11|17|13|19|03|22|05|16|07|18|01|20|04|10|06|12|00|14|02|08| 
16|22|10|20|08|14|17|23|04|18|02|12|11|21|05|19|00|06|09|15|03|13|01|07| 
17|23|11|21|09|15|16|22|05|19|03|13|10|20|04|18|01|07|08|14|02|12|00|06| 
18|12|19|06|13|07|20|14|21|00|15|01|22|08|23|02|09|03|16|10|17|04|11|05| 
19|13|18|07|12|06|21|15|20|01|14|00|23|09|22|03|08|02|17|11|16|05|10|04| 
20|14|22|08|16|10|18|12|23|02|17|04|19|06|21|00|11|05|13|07|15|01|09|03| 
21|15|23|09|17|11|19|13|22|03|16|05|18|07|20|01|10|04|12|06|14|00|08|02| 
22|16|20|10|14|08|23|17|18|04|12|02|21|11|19|05|06|00|15|09|13|03|07|01| 
23|17|21|11|15|09|22|16|19|05|13|03|20|10|18|04|07|01|14|08|12|02|06|00| 

下面是n = 4的事实根据。为了紧凑,我将最后一位数字保持为零。

000|001|010|011|020|021|100|101|110|111|120|121|200|201|210|211|220|221|300|301|310|311|320|321| 
001|000|011|010|021|020|101|100|111|110|121|120|201|200|211|210|221|220|301|300|311|310|321|320| 
010|020|000|021|001|011|110|120|100|121|101|111|210|220|200|221|201|211|310|320|300|321|301|311| 
011|021|001|020|000|010|111|121|101|120|100|110|211|221|201|220|200|210|311|321|301|320|300|310| 
020|010|021|000|011|001|120|110|121|100|111|101|220|210|221|200|211|201|320|310|321|300|311|301| 
021|011|020|001|010|000|121|111|120|101|110|100|221|211|220|201|210|200|321|311|320|301|310|300| 
100|101|200|201|300|301|000|001|210|211|310|311|010|011|110|111|320|321|020|021|120|121|220|221| 
101|100|201|200|301|300|001|000|211|210|311|310|011|010|111|110|321|320|021|020|121|120|221|220| 
110|120|210|220|310|320|010|020|200|221|300|321|000|021|100|121|301|311|001|011|101|111|201|211| 
111|121|211|221|311|321|011|021|201|220|301|320|001|020|101|120|300|310|000|010|100|110|200|210| 
120|110|220|210|320|310|020|010|221|200|321|300|021|000|121|100|311|301|011|001|111|101|211|201| 
121|111|221|211|321|311|021|011|220|201|320|301|020|001|120|101|310|300|010|000|110|100|210|200| 
200|300|100|301|101|201|210|310|000|311|001|211|110|320|010|321|011|111|120|220|020|221|021|121| 
201|301|101|300|100|200|211|311|001|310|000|210|111|321|011|320|010|110|121|221|021|220|020|120| 
210|310|110|320|120|220|200|300|010|321|020|221|100|301|000|311|021|121|101|201|001|211|011|111| 
211|311|111|321|121|221|201|301|011|320|021|220|101|300|001|310|020|120|100|200|000|210|010|110| 
220|320|120|310|110|210|221|321|020|300|010|200|121|311|021|301|000|100|111|211|011|201|001|101| 
221|321|121|311|111|211|220|320|021|301|011|201|120|310|020|300|001|101|110|210|010|200|000|100| 
300|200|301|100|201|101|310|210|311|000|211|001|320|110|321|010|111|011|220|120|221|020|121|021| 
301|201|300|101|200|100|311|211|310|001|210|000|321|111|320|011|110|010|221|121|220|021|120|020| 
310|210|320|110|220|120|300|200|321|010|221|020|301|100|311|000|121|021|201|101|211|001|111|011| 
311|211|321|111|221|121|301|201|320|011|220|021|300|101|310|001|120|020|200|100|210|000|110|010| 
320|220|310|120|210|110|321|221|300|020|200|010|311|121|301|021|100|000|211|111|201|011|101|001| 
321|221|311|121|211|111|320|220|301|021|201|011|310|120|300|020|101|001|210|110|200|010|100|000| 
+0

如果你不执着于字典顺序,这是不是可以类似于将两个值小于'N'不到一致的方式'N'一个值? – 2014-09-22 17:57:49

+0

@גלעדברקן我不这么认为。假设我们将f(R,n,i,j)定义为取得排列的一些排序R的函数(因此R是唯一排列的列表),n是排列的长度(元素0到n-1; | R | = n!),而i和j是R中两个输入排列的索引,则f(R,n,i,j)是R中输出排列的索引。我不在乎R是,但我不认为这是一个微不足道的问题。也许我误解了你的评论 - 你能澄清还是举个例子? – Dave 2014-09-22 18:11:00

+0

对不起,我错误地认为'n'是排列的数量。在那种情况下,我的意思是将两个小于或等于| R |的值转换到小于或等于| R |的一个值以一致的,不平凡的方式。 – 2014-09-22 18:41:57

回答

0

我发现的算法中的线性时间排列和队伍之间进行转换。这不是我想要的,但可能足够好。事实证明,我不关心字典顺序的事实很重要。这使用的排名很奇怪。我要给出两个函数,一个从一个等级转换为一个排列,另一个执行相反的操作。

一是unrank(去从排名到置换)

Initialize: 
n = length(permutation) 
r = desired rank 
p = identity permutation of n elements [0, 1, ..., n] 

unrank(n, r, p) 
    if n > 0 then 
    swap(p[n-1], p[r mod n]) 
    unrank(n-1, floor(r/n), p) 
    fi 
end 

接下来,排名:

Initialize: 
p = input permutation 
q = inverse input permutation (in linear time, q[p[i]] = i for 0 <= i < n) 
n = length(p) 

rank(n, p, q) 
    if n=1 then return 0 fi 
    s = p[n-1] 
    swap(p[n-1], p[q[n-1]]) 
    swap(q[s], q[n-1]) 
    return s + n * rank(n-1, p, q) 
end 

这是伪代码。对于我的项目,我会小心处理一份p的副本,所以在计算排名时我不会改变它。

这两者的运行时间都是O(n)。

有一个不错的,可读的文件,解释为什么这个工程:排名& Unranking排列组合的线性时间,通过Myrvold & Ruskey,信息处理快报79卷第6期,2001年9月30日,页281-284。

http://webhome.cs.uvic.ca/~ruskey/Publications/RankPerm/MyrvoldRuskey.pdf

0

如果,除了R,你不执着于一个特别是对任一,我们可以重新排列功能,方便可能的答案。下面的函数newPerm将与R相关的列表以与“索引到”的排列函数相同的一致性排列。

以下示例未针对效率进行优化(例如,可以在O(n)中完成排名/排序)。最后两行输出将重新定义的排列函数与“索引”排列函数进行比较 - 如您所见,它们在映射到排列集合时都会生成相同数量的唯一排列。函数f将是该问题的答案。

Haskell代码:

import Data.List (sort,permutations) 
import Data.Maybe (fromJust) 

sortedPermutations = sort $ permutations [0,1,2,3,4,5,6] 

rank p = fromJust (lookup p rs) where rs = zip sortedPermutations [0..] 

unrank r = fromJust (lookup r ps) where ps = zip [0..] sortedPermutations 

tradPerm p s = foldr (\a b -> s!!a : b) [] p 

newPerm p s = unrank (f (rank p) (rank s)) 

f r1 r2 = let l = r1 - r2 in if l < 0 then length sortedPermutations + l else l 

输出:

*Main Data.List> unrank 3 
[0,1,2,3,5,6,4] 

*Main Data.List> unrank 8 
[0,1,2,4,5,3,6] 

*Main Data.List> f 3 8 
5035 

*Main Data.List> newPerm [0,1,2,3,5,6,4] [0,1,2,4,5,3,6] 
[6,5,4,3,0,2,1] 

*Main Data.List> rank [6,5,4,3,0,2,1] 
5035 

*Main Data.List> length $ group $ sort $ map (tradPerm [1,2,5,0,4,3,6]) sortedPermutations 
5040 

*Main Data.List> length $ group $ sort $ map (newPerm [1,2,5,0,4,3,6]) sortedPermutations 
5040 
+0

如果“f 3 8 = 5035”意味着用第三个排列的元素对第八个排列进行索引产生第5035个排列,并且第三个和第八个排列在您的输出中描述,那么我们应该有“unrank 5035 = [0 ,1,2,4,3,6,5]。也就是说,这似乎不具有这样的性质,即输出秩是通过用第一排列的元素索引到第二排列而获得的排列的排名。我只是把它放在你给出的输出上,因为我不知道Haskell。 – Dave 2014-09-23 23:55:01

+0

@DaveGalvin谢谢你的评论。我认为你所说的“索引到”意味着“排列”,那就是,我正在使用第三个排列来排列第8个排列(我猜我的'i'和'j'是在我的例子中切换的,oops),因为在这个例子中,我重新定义“排列”意味着'unrank(f我的“索引到”或“排列”通过函数newPerm发生,它产生了[6,5,4,3,0,2,1 ]'。正如它应该的那样,不合规的5035也产生了[6,5,4,3,0,2,1]'。我没有完全测试或证明它,只是尝试一些非常规的可能一致的东西。 – 2014-09-24 01:22:21

+0

@DaveGalvin关于Haskell - 你可以或多或少地阅读代码,因为你会数学。 'rank'和'unrank'只是在列表中查找索引或者排列,'tradPerm'就是你传统的排列方式(通过“索引到”)。 – 2014-09-24 01:28:01