我目前正在阅读安德鲁·亨特和戴维·托马斯的《实用程序员》。我遇到了这段话:
“例如,假设您有一个例程来处理100条记录需要1s。要处理1000条需要多长时间?如果您的代码是O(1),那么它仍将花费1s。如果O(lgn),那么您可能要等待大约3s。O(n)将线性增加至10s,而O(nlgn)将花费大约33s。如果您不幸遇到O(n ^ 2)例程,然后在它执行其工作时坐下来100秒钟。如果您使用的是指数算法O(2 ^ n),则可能要冲杯咖啡-您的例程应在10秒钟左右结束(263)年。”
有人可以告诉我他如何计算O(lgn),O(nlgn),O(n ^ 2)和O(2 ^ n)情况的数学方法吗?我知道O(1)是实时的,所以n =任何东西都等于1。线性O(n)情况也很有意义,因为n = 1000条记录只是10x n = 100条记录,这意味着运行时间为1s * 10 = 10s。
答案 0 :(得分:2)
我不确定我是否同意发布的 actual 数据,但是这个概念是可靠的。您需要做的是弄清工作量根据输入值的变化。
以O(lg N)
为例(其中lg
是log10
的表示法),我们将假设一个常数乘数c
来获取时间(这个假设是很有可能是为什么我的数字与书中的数字不同。
因此,(c * lg 100)
给您1秒钟的时间,并且自(lg 100 = 2)
起,这意味着(c = 1/2)
。将其应用于输入大小1000,(1/2 * lg 1000)
将为您提供1.5秒。
对于O(NlgN)
,(c * 100 * lg 100)
给您1秒钟的时间,并且自(100 lg 100 = 200)
起,这意味着(c = 1/200)
。将其应用于输入大小1000,(1/200 1000 lg 1000)
将为您提供15秒。
对于O(N2)
,(c * 1002)
给您1秒钟的时间,并且自(1002 = 10,000)
起,这意味着(c = 1/10,000)
。将其应用于输入大小1000,1/10,000 * 10002
将为您提供100秒。
最后是O(2N)
案。
由于(c * 2100)
给您1秒,因此意味着(c = 1/2100)
。将其应用于输入大小1000,(1/2100 * 21000)
会给您(由于数字越来越大,我将对此加以介绍):
(1/(2^100)) * 2^1000
= 2^1000 / 2^100
= 2^900
= 8.4 * 10^270 seconds
= 2.6 * 10^263 years (using 86,400 secs/day, 365 days/year).
那是真正巨大的数字来自何处。简而言之:
Complexity Duration From book
---------- -------- ---------
O(1) 1 s 1 s
O(lgN) 1.5 s 3 s
O(N) 10 s 10 s
O(NlgN) 15 s 33 s
O(N^2) 100 s 100 s
O(2^N) 10^263 y 10^263 y
与书中所见不完全相同,但与数量级非常吻合,这可能是进行复杂度分析时希望得到的最好结果。