这个问题是关于费舍尔-耶茨算法的,该算法用于返回给定数组的随机混洗。在维基百科页面称,其复杂度为O(n),但我认为这是O(n log n)的。
在每个迭代i中,在1和i之间选择一个随机整数。简单地将整数写到内存中就是O(log i),由于有n次迭代,所以总数为
O(log 1)+ O(log 2)+ ... + O(log n)= O(n log n)
天真的算法效果不佳。我在这里想念什么吗?
注意:天真的算法是在(0,1)区间为每个元素分配一个随机数,然后根据分配的数字对数组进行排序。
这个问题是关于费舍尔-耶茨算法的,该算法用于返回给定数组的随机混洗。在维基百科页面称,其复杂度为O(n),但我认为这是O(n log n)的。
在每个迭代i中,在1和i之间选择一个随机整数。简单地将整数写到内存中就是O(log i),由于有n次迭代,所以总数为
O(log 1)+ O(log 2)+ ... + O(log n)= O(n log n)
天真的算法效果不佳。我在这里想念什么吗?
注意:天真的算法是在(0,1)区间为每个元素分配一个随机数,然后根据分配的数字对数组进行排序。
Answers:
我怀疑像大多数算法一样,这里读写位数字的成本被假定为常数。只要您不被带走并使P和PSPACE意外崩溃,这就是轻微的罪过。
计算的标准模型假定对O(log n)位整数的算术运算可以在恒定时间内执行,因为这些运算通常在硬件中进行。因此,在Fisher-Yates算法中,“将整数i写入内存”仅需要O(1)时间。
当然,从位操作角度分析算法是非常有意义的,但是位成本模型对实际行为的预测较少。即使是简单的循环也for i = 1 to n: print(i)需要O(n log n)位操作。
这是对“ [Fisher-Yates算法]并不比朴素算法好。我在这里遗漏了什么吗?”的答案。您在问题中问过的。
在使用实数的“幼稚”算法中:您使用多少位精度?如果您要计算位复杂度(就像您对Fisher-Yates所做的那样),并且该算法使用k个随机位作为实数,则其运行时间为Ω(kn log n),因为将两个k-位实数需要Ω(k)时间。但是k必须至少为Ω(log n)才能防止两个元素映射到相同的实数,这意味着该算法需要Ω(n log 2 n)的时间,比Fisher-Yates混洗慢了a记录因子n。
如果仅计算算术和比较运算的数量而忽略它们的位复杂度,则Fisher-Yates为Θ(n),而算法为Θ(n log n),仍然相距log n。
对于此问题,整数没有什么特别的。
例如,如果哈希函数必须读取整个值以计算其哈希值,则哈希表(存储任何类型的值)的访问时间不会为O(1)。n个唯一元素平均需要log n个位来表示,无论您的表示多么聪明,任何读取其整个输入的哈希函数都至少需要花费相同的时间来计算。在实践中,它们比红黑树要快,但渐近而言它们并没有更好。
randomwalker引用的问题是关于POPL 2008论文(http://portal.acm.org/citation.cfm?doid=1328438.1328460),在此处进行了讨论:http : //blog.computationalcomplexity.org/2009/05/shaving- logs-with-unit-cost.html
在那篇文章中,兰斯·福特诺(Lance Fortnow)描述了一个学生,他如何抱怨排序实际上需要n log ^ 2 n次,如果我们必须读取两个元素的所有log n位以进行比较,这似乎是一个合理的反对。
维基百科页面说它的复杂度是O(n),但我认为它是O(n log n)。
实际上,在排序为O(n log n)的模型中,O(n log n)是此问题的下限。如果所有排列的可能性均等,则该算法作为从随机流到排列的函数必须是排斥的。有n!因此,在决策树模型之类的东西中,存在至少长度为O(log n!)= O(n log n)的分支。