我想知道下面解释的任务在理论上是否可行,如果可以,那么我该如何做。
给定一个由 N
个元素组成的空间(即所有介于 0
和 N-1
之间的数字)。让我们看看在该空间上的所有排列,并将其称为 S
。第 i
个 S
成员,可以标记为 S[i]
,是具有词典序号码 i
的排列。
例如,如果 N
是3,则 S
是以下排列列表:
S[0]: 0, 1, 2
S[1]: 0, 2, 1
S[2]: 1, 0, 2
S[3]: 1, 2, 0
S[4]: 2, 0, 1
S[5]: 2, 1, 0
当然,当考虑到一个大的
N
时,这个空间变得非常大,确切地说是N!
。现在,我已经知道如何根据索引号
i
获取排列,以及如何进行反转(获取给定排列的字典序编号)。 但我想要更好的东西。有些排列本身可能非常庞大。例如,如果您正在查看
N=10^20
。(S
的大小将是(10^20)!
,我相信这是我在Stack Overflow问题中提到过的最大的数字 :)如果您只是在查看该空间上的随机排列,那么它会非常大,您甚至无法将整个排列存储在硬盘上,更别说按字典顺序计算每个项目。我想要的是能够对该排列进行项目访问,并获取每个项目的索引。也就是说,给定
N
和i
来指定一个排列,有一个函数可以接受索引号并找到驻留在该索引中的数字,另一个函数可以接受数字并找到它所在的索引。我希望以O(1)
的时间完成这些操作,因此不需要存储或迭代排列中的每个成员。你说这是疯狂的吗?不可能吗?也许是这样。但请考虑一下:像AES这样的块密码本质上是一种置换,它几乎可以完成我上面概述的任务。AES的块大小为16字节,这意味着N是256^16,约为10^38。(S的大小无关紧要)它的大小惊人地达到了(256^16)!,约为10^85070591730234615865843651857942052838,这打破了我在Stack Overflow上提到的“最大数”记录 :)
每个AES加密密钥都指定了一个单一的排列在N=256^16上。这个排列无法完整地存储在您的计算机上,因为其成员比太阳系中的原子数还多。但是,它允许您进行项目访问。通过使用AES加密数据,您正在逐块查看数据,并且对于每个块(
range(N)
的成员),您输出加密块,该成员是在排列中原始块的索引号。解密时,您执行反向操作(查找块的索引号)。我相信这是以O(1)完成的,虽然我不确定,但无论如何速度非常快。使用AES或任何其他块密码的问题在于它限制了您非常特定的N,并且可能仅捕获可能排列的一小部分,而我想能够使用任何我喜欢的N,并且可以在任何排列S[i]上进行项目访问。
是否可能在给定大小N和排列编号i的情况下获得O(1)的排列项访问?如果是,怎么做?
(如果我在这里得到编程答案,我希望它们是用Python编写的。)
更新:
一些人指出排列数本身非常巨大,仅仅读取这个数字就会使任务变得不可行。那么,我想修改我的问题:给定一个排列的词典序号的factoradic representation,是否有可能以O(尽可能小的)的时间得到排列中的任何项?