当我遇到这个声明时(我用渐近符号),我正在阅读Thomas H. Corman的算法简介
当a> 0时,任何线性函数a + b都在O(n ^ 2)中,这基本上通过取c = a + | b |来验证。和no = max(1,-b / a)
我无法理解为什么 O(n ^ 2)而不是 O(n)。何时 O(n)上限失败。
例如,对于3n+2
,根据书籍
3n+2 <= (5)n^2 n>=1
但这也很好
3n+2 <= 5n n>=1
那么为什么上限是 n ^ 2 ?
答案 0 :(得分:3)
我找到了本书的相关部分。实际上摘录来自介绍大O符号和亲戚的章节。
big-O的正式定义是所讨论的函数不会比比较函数渐近地增长。它没有说明函数是否渐渐变慢,所以:
f(n) = n
位于O(n)
,O(n^2)
和O(e^n)
,因为n
的渐进速度不会比任何这些都快。但是n
不在O(1)
。
O(n)
中的任何功能也位于O(n^2)
和O(e^n)
。
如果你想描述紧的渐近边界,你可以使用big-Θ符号,它是在书中的大O符号之前引入的。 f(n) ∊ Θ(g(n))
表示f(n)
不会比g(n)
渐近地增长,反之亦然。因此f(n) ∊ Θ(g(n))
相当于f(n) ∊ O(g(n))
和g(n) ∊ O(f(n))
。
所以f(n) = n
位于Θ(n)
但不在Θ(n^2)
或Θ(e^n)
或Θ(1)
。
另一个例子:f(n) = n^2 + 2
位于O(n^3)
但未位于Θ(n^3)
,位于Θ(n^2)
。
您需要将O(...)
视为一个集合(这就是为什么使用集合理论“元素”-symbol)。 O(g(n))
是所有函数的集合,不会比g(n)
渐近地增长,而Θ(g(n))
是一组函数,它们既不会渐近地增长也不会比g(n)
慢。因此,合理的结果是Θ(g(n))
是O(g(n))
的一个子集。
通常使用=
代替∊
符号,这实际上是误导性的。它是纯符号,不与实际=
共享任何属性。例如1 = O(1)
和2 = O(1)
,但不是1 = O(1) = 2
。最好避免使用=
作为big-O表示法。尽管如此,您稍后会看到=
符号很有用,例如,如果您想表达其余术语的复杂性,例如:f(n) = 2*n^3 + 1/2*n - sqrt(n) + 3 = 2*n^3 + O(n)
,这意味着渐近函数的行为类似于2*n^3
并且被忽略的部分渐近地增长得比n
快。
所有这些都反对通常使用big-O表示法。您经常会发现由它定义的算法的时间/内存复杂度,实际上它应该由big-Θ符号定义。例如,如果您在O(n^2)
中有一个算法,在O(n)
中有一个算法,那么第一个算法实际上仍然可以渐近更快,因为它也可能在Θ(1)
中。造成这种情况的原因有时可能是紧密的Θ-bound不存在或者对于给定的算法是不知道的,所以至少big-O可以保证事情不会比给定的边界花费更长的时间。按照惯例,你总是试图给出已知最低的大O界限,而这在正式上是不必要的。
答案 1 :(得分:-1)
大O符号的正式定义(来自维基百科)说:
f(x)= O(g(x))为x→∞
当且仅当存在正常数M以便对所有人而言 足够大的x,f(x)值最多M乘以g(x) 绝对值。也就是说,当且仅当存在时,f(x)= O(g(x)) 正实数M和实数x0使得
| f(x)|≤M| g(x)|对于所有x&gt; x 0(x足够大的意思)
在我们的案例中,我们可以轻松地显示
| an + b | &LT; | an + n | (对于n足够大,即当n> b时)
然后| an + b | &LT; (A + 1)| N |
由于+ 1是常数(对应于形式定义中的M),绝对是
an + b = O(n)
你有理由怀疑。