试图证明/反驳算法的复杂性分析
Posted
技术标签:
【中文标题】试图证明/反驳算法的复杂性分析【英文标题】:Trying to prove/disprove complexity analysis of an algorithm 【发布时间】:2012-04-16 07:00:04 【问题描述】:我不是在寻找上述问题的算法。我只是希望有人评论我的答案。
我在一次采访中被问到以下问题:
如何从一大堆数字中获取前 100 个数字(无法放入 记忆)
这就是我所说的:
将数字分成每批 1000 个。在“O(1)”时间内对每个批次进行排序。到目前为止,总时间为 O(n)。现在从第一批和第二批(在 O(1) 中)中获取第 100 个数字。从上面计算的数字和第三批中取出第一个 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
找到了更好的答案【问题讨论】:
我稍微编辑了这个问题,因为您不是在寻找给定问题的答案 - 线程的主题应该反映您的要求。如果您能想到一个更好的主题标题,请重新编辑,因为我给出的标题似乎并不完美。 如果整组数字都装不下内存,有多少内存可以做呢? @Donotalo:请注意,OP 对问题的解决方案不感兴趣,但对分析建议的解决方案感兴趣。 您的面试官是另一位通过阅读博客文章“学习”了大 O 符号的技术人员。由于移动空间有限(尽管很大),甚至 chess 也可以在 O(1) 时间内解决。 @Donatalo 如果你想确定复杂度,搜索一个大小为 n 的未排序列表以确定元素是否存在,复杂度为 o(n)。你不能简单地插入一个具体的数字,因为那样你就改变了任务。如果将原始列表分成 100 项的多个列表。然后搜索所有这些列表。搜索大小为 100 的列表的复杂度为 O(1)。如果您不同意,请研究 Big-O 的定义(例如here)。所以搜索所有较小列表的复杂度仍然是 O(n) 【参考方案1】:面试官错了,但考虑一下原因很有用。您所说的是正确的,但是您依赖于一个未说明的假设。可能,面试官做出了不同的假设。
如果我们说对 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。
【讨论】:
【参考方案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)
有非常大的常数。
【讨论】:
以上是关于试图证明/反驳算法的复杂性分析的主要内容,如果未能解决你的问题,请参考以下文章