这是我学习数据结构的第一门课程,每节课/助教讲座中我们都会谈到O(log(n))
。也许这是一个愚蠢的问题,但我很希望有人能够解释一下它到底是什么意思!
这是我学习数据结构的第一门课程,每节课/助教讲座中我们都会谈到O(log(n))
。也许这是一个愚蠢的问题,但我很希望有人能够解释一下它到底是什么意思!
这意味着所讨论的事物(通常是运行时间)按照其输入规模的对数比例进行缩放。
大O符号并不表示一个精确的等式,而是一个上限。例如,以下函数的输出都是O(n):
f(x) = 3x
g(x) = 0.5x
m(x) = x + 5
因为随着x的增加,它们的输出线性增加 - 如果f(n)
和g(n)
之间存在6:1的比率,则f(10*n)
和g(10*n)
之间也将大致存在6:1的比率,以此类推。
至于O(n)
或O(log n)
哪个更好,考虑一下:如果n = 1000
,那么log n = 3
(以10为底的对数)。你希望你的算法需要多长时间才能运行:1000秒还是3秒?
f(x)
、g(x)
和m(x)
也都是O(n^2)。但在性能分析的上下文中,我们希望得到最紧密的限制(即限制给定算法性能曲线的最小函数),以便给出算法性能的“最坏情况”想法。 - Minh Tran2 ** 4
,而在Amber的代码中,例子是10 ** 3
;如何确定参数? - MadHattern
的输入,一个时间复杂度为O(n)
的算法将执行与n
成正比的步骤,而另一个时间复杂度为O(log(n))
的算法将执行大约log(n)
个步骤。log(n)
小于n
,因此时间复杂度为O(log(n))
的算法更好。因为它会快得多。O(logn) 表示算法的最大运行时间与输入大小的对数成比例。 O(n) 表示算法的最大运行时间与输入大小成比例。
基本上,O(something) 是算法指令数量(原子指令)的上限。因此,O(logn) 比 O(n) 更紧密,也更好地适用于算法分析。但所有 O(logn) 的算法也都是 O(n),但反过来则不一定成立...
正式定义:
若存在常数C和x0,对于每个x>x0, |g(x)|<= C|f(x)|,则g(x) = O(f(x))。
因此,如果你为问题P找到了复杂度为O(f(n))的算法A,那么你可以说,当n通常是输入大小时,你的算法执行步骤的数量渐近地小于或等于f(n)。(n可以是任何值)
更多信息请参考:http://en.wikipedia.org/wiki/Big_O_notation。
O(1)总是比O(log n)快吗?
O(1)表示算法的运行时间与输入大小无关,并受到常数'c'的限制。而O(log n)表示当输入大小'n'指数增长时,运行时间将线性增长。
需要注意的是,在某些情况下,O(log n)可能比O(1)快,但当n增长时,O(1)将优于O(log n),因为O(1)不依赖于输入大小n。考虑这两个代码片段:
Code 1:
function show(){
for(let i = 2; i <= 5; i++){
console.log("Hello");
}
}
Code 2:
function showN(n){
for(let i = 2; i <= n; i=i*2){
console.log("Hello");
}
}
Code 1的运行时间为O(1),因为它与输入大小'n'无关,而Code 2的运行时间为O(log n)。
案例:O(log n)优于O(1) 让我们假设show函数执行需要1毫秒。
当n=2时,Code 1将花费4毫秒执行,而Code 2只需1毫秒执行。在这种情况下,O(log n)优于O(1)。
案例:O(1)优于O(log n) 随着输入大小'n'增加,O(1)将优于O(log n)。让我们看一个例子,假设n = 2048,现在Code 1执行仍然需要4毫秒,但Code 2执行需要11毫秒。在这种情况下,O(1)优于O(log n)。
结论: 如上述案例所示,O(1)算法并非总是比O(log n)更快。有时,O(log n)会优于O(1),但随着输入大小'n'的增加,O(log n)的执行时间会超过O(1)。