我不是在寻找上述问题的算法。我只是希望有人对我的回答发表评论。
在接受采访时我被问到以下问题:
如何从大量数字中获得前100个数字(不能适应 存储器)
这就是我所说的:
将每个数量分为1000个。在“O(1)”时间内对每批次进行排序。到目前为止所花费的总时间是O(n)。现在从第1批和第2批中取出前100个数字(在O(1)中)。从上面计算的nos和第3批中取第1 100个,依此类推。这将总共需要O(n) - 所以它是一个O(n)算法。
面试官回答说,整理了一批1000个。不会花费O(1)的时间,因此不会在批次中挑出前100名,经过大量的讨论他说,他没有问题算法花费O(n)时间,他只是我的一个问题是,对批次进行排序需要花费O(1)时间。
我的解释是1000不依赖于输入(n)。无论n是什么,我总是会批量生产1000个。如果你需要计算,排序需要O(1000 * log 1000)),这基本上是O(1)。
如果你必须进行适当的计算,那就是
1000 * log 1000对一批进行排序 排序(n / 1000)这样的批次 需要1000 * log 1000 * n / 1000 = O(n * log(1000))时间= O(n)时间
我也向很多朋友询问了这件事,虽然他们同意我的意见,但部分同意。 所以我不知道我的推理是否100%准确(请批评即使它是99%正确)。
请记住,这篇文章并不是要求上述问题的答案。我已经在Retrieving the top 100 numbers from one hundred million of numbers
找到了更好的答案答案 0 :(得分:2)
确实是O(n)
- 但是常量非常高,特别是考虑到你需要从文件系统中读取每个元素两次 [一次在排序中,一次在第二次阶段]和文件系统访问,很多比内存访问慢。由于这可能是算法的瓶颈,因此您的解决方案可能运行速度慢两倍然后使用优先级队列。
请注意,对于常量top 100
,即使是天真的解决方案也是O(n)
:
for each i in range(1,100):
x <- find highest element
remove x from the list
append x to the solution
此解决方案也是O(n)
,因为您有100次迭代,在每次迭代中,您需要对列表进行2次遍历[通过一些优化,每次迭代可以完成1次遍历]。因此,遍历总数严格小于1000,并且没有更多因素取决于大小,因此解决方案是O(n)
- 但它绝对是一个糟糕的解决方案。
我认为面试官意味着你的解决方案 - 虽然O(n)
有非常大的常量。
答案 1 :(得分:2)
面试官错了,但考虑原因很有用。你所说的是正确的,但有一个未说明的假设,你依赖。可能,面试官正在做出不同的假设。
如果我们说排序1000个数字是O(1),我们有点非正式。具体来说,我们的意思是,在N变为无穷大的极限中,存在大于或等于对1000个数字进行排序的成本的常数。由于对固定大小集进行排序的成本与N无关,因此该限制也不依赖于N.因此,当N变为无穷大时,它是O(1)。
慷慨的解释是,面试官希望您以不同的方式对待排序步骤。您可以更精确地说它是O(M * log(M)),因为M变为无穷大(或者M变为N,如果您愿意),M表示数字批次的大小。这将为你的方法做出总体O(N * log(M)),因为N和M都接近无穷大。当然,这不是你描述的限制。
严格地说,没有指定限制就说O(1)是没有意义的。人们通常不需要为算法而烦恼,因为从上下文中可以清楚地看出:通常采用的限制是单个参数接近无穷大。仅考虑N时,您的描述是正确的,但您可以考虑的不仅仅是N.