所以我一直在尝试理解Big O符号,但仍有一些我很困惑的事情。所以我一直在读,如果某些东西是O(n),那么通常指的是算法的最坏情况,但是它并不一定要指最坏的情况场景,这就是为什么我们可以说插入排序的最佳情况例如是O(n)。但是,我无法理解这意味着什么。我知道如果最坏情况是O(n ^ 2),这意味着在最坏情况下表示算法的函数增长不快于n ^ 2(存在上限)。但如果你有O(n)作为最好的情况,我应该怎么读呢?在最好的情况下,算法增长不比n快?我的图片是以n为上限的图形,如
如果算法的最佳情况是O(n),则n是算法运算在最佳情况下增长的速度的上限,因此它们的增长速度不能比n ...但不会这意味着他们可以以O(log n)或O(1)的速度增长,因为它们低于上限?这没有意义,因为O(log n)或O(1)是比O(n)更好的场景,所以O(n)不是最好的情况吗?我很失落lol
答案 0 :(得分:11)
Big-O,Big-Θ,Big-Ω独立于最坏情况,平均情况和最佳情况。
符号f(n)= O(g(n))意味着f(n)增长不会比g(n)的某个常数倍增长。
符号f(n)=Ω(g(n))表示f(n)增长不比g(n)的某些常数倍慢。
符号f(n)=Θ(g(n))表示上述两种情况均为真。
请注意,这里的f(n)可能表示输入大小为n的程序的最佳情况,最坏情况或“平均”运行时间。
此外,“平均”可以有很多含义:它可以表示平均输入或平均输入大小(“预期”时间),或者它可以表示 in从长远来看(摊销时间),或两者兼而有之。
通常,人们对程序的最坏情况运行时间感兴趣,在整个程序的运行时间内摊销(所以如果某些成本 n 最初但是对于下一个 n 元素只花费1次,平均每个元素的成本为2)。这里衡量的最有用的是最坏情况下的最小上限;所以,通常情况下,当你看到有人要求程序的Big-O时,这就是他们正在寻找的东西。
同样,为了证明问题本质上是困难的,人们可能会试图证明最坏情况(或者可能是平均情况)的运行时间至少 a一定数量(例如,指数) 你会为这些使用Big-Ω表示法,因为你正在寻找这些符号的下限。
然而,在最坏情况和Big-O之间,或者最佳情况和Big-Ω之间没有特殊关系 两者都可以用于其中之一,只是其中一个比另一个更典型。
因此,最佳案例的上限并不是非常有用。是的,如果算法总是花费O(n)时间,那么你可以说它是O(n)在最好的情况下,以及平均值,以及最坏的情况。这是一个非常好的陈述,除了最好的情况通常是非常微不足道的,因此本身并不有趣。
此外,请注意f(n)= n = O(n 2 ) - 这在技术上是正确的,因为f比n 2 增长更慢,但是它无用因为它不是最小上限 - 有一个非常明显的上限比这个更有用,即O(n)。所以,是的,非常欢迎您说程序的最佳/最差/平均情况运行时间是O(n!)。这在数学上是完全正确的。它只是没用,因为当人们要求Big-O时,他们对至少上限感兴趣,而不仅仅是随机上限。
值得注意的是可能只是将程序的运行时间描述为f(n)。 运行时间通常取决于输入本身,而不仅仅是其大小。例如,甚至查询可能很容易回答,而奇数查询需要很长时间才能回答。
在这种情况下,您不能只将 f 作为 n 的函数 - 它也将依赖于其他变量。最后,请记住,这只是一组数学工具;这是你的工作,弄清楚如何将它应用到你的程序,并找出衡量一个有趣的东西。以有用的方式使用工具需要一些创造力,数学也不例外。
答案 1 :(得分:3)
非正式地说,最佳案例有O(n)复杂度意味着当输入遇到 某些条件(即对于所执行的算法最好),然后是计数 在该最佳情况下执行的操作相对于n是线性的(例如,是1n或1.5n或5n)。 因此,如果最好的情况是O(n),通常这意味着在最好的情况下它是完全线性的 关于n(即渐近地不小于且不大于) - 见(1)。当然, 如果在最好的情况下,可以证明相同的算法最多执行c * log N操作 (其中c是一些常数),那么这个算法的最佳案例复杂性将是非正式的 表示为O(log N)而不是O(N),人们会说最好的情况是O(log N)。
从形式上讲,“算法的最佳案例复杂度为O(f(n))” 是一种非正式和错误的方式来说“算法的复杂性 是Ω(f(n))“(在Knuth定义的意义上 - 见(2))。
另见:
(1)Wikipedia "Family of Bachmann-Landau notations"
(2)Knuth's paper "Big Omicron and Big Omega and Big Theta"
(3) Big Omega notation - what is f = Ω(g)?
(4) What is the difference between Θ(n) and O(n)?
(5) What is a plain English explanation of "Big O" notation?
答案 2 :(得分:2)
我发现将O()
视为关于比率而不是关于边界更容易。它被定义为边界,因此这是一种有效的思考方式,但考虑“如果我将算法的输入数量/大小加倍,我的处理时间加倍({{ 1}}),四重(O(n)
)等......“。以这种方式思考它会使它变得不那么抽象 - 至少对我而言......