以下如何相当于O(N)

时间:2017-09-01 02:56:14

标签: algorithm big-o

我正在阅读一个例子,其中以下等同于O(N):

 O(N + P), where P < N/2
 O(N + log N)

有人可以用外行的方式解释上面两个例子与O(N)是一样的吗?

5 个答案:

答案 0 :(得分:1)

我们总是选择更大的一个。

在这两种情况下,N都大于另一部分。

在第一种情况P < N/2 < N

在第二种情况下log N < N

因此,两种情况下的复杂性都是O(N)

答案 1 :(得分:1)

  

设f和g是在实数的某个子集上定义的两个函数。一个人写道

     

f(x)= O(g(x))为x - >无限

     

当且仅当存在正常数M使得对于所有足够大的x值,f(x)的绝对值最多为M乘以g(x)的绝对值。也就是说, f(x)= O(g(x))当且仅当存在正实数M和实数x0时

     

<强> | F(X)| &lt; = M | g(x)|对于所有x&gt; X0

所以在你的情况下1:

f(N) = N + P <= N + N/2 

我们可以设置M = 2然后:

|f(N)| <= 3/2|N| <= 2|N| (N0 could any number) 

所以:

N+p = O(N)

在你的第二种情况下,我们也可以设置M = 2和N0 = 1来满足:

|N + logN| <= 2 |N| for N > 1

答案 2 :(得分:1)

Big O notation通常只提供函数wiki的增长率的上限。这两种情况的含义,如P < NlogN < N。因此O(N + P) = O(2N) = O(N)O(N + log N) = O(2N) = O(N)相同。希望能回答你的问题。

答案 3 :(得分:0)

为了便于理解,您可以假设O(n)表示复杂性是n的order,而O符号表示上限(或最差的复杂性)案件)。所以,当我说O(n+p)时,它表示n + p的顺序。

让我们假设在最坏的情况下p = n / 2,那么n + n / 2的顺序是什么?它仍然是O(n),即线性,因为常量确实构成了Big-O表示法的一部分。

类似,对于O(n+logn),因为logn永远不会大于n。因此,整体复杂性变得线性。

答案 4 :(得分:0)

简而言之

如果N是函数而C是常数:

O(N+N/2)

If C=2, then for any N>1 :
    (C=2)*N > N+N/2,
    2*N>3*N/2,
    2> 3/2 (true)

O(N+logN)

If C=2, then for any N>2 :
    (C=2)*N > N+logN,
    2*N > N+logN,
    2>(N+logN)/N,
    2> 1 + logN/N (limit logN/N is 0),
    2>1+0 (true)

反例O(N^2)

No C exists such that C*N > N^2 :
    C > N^2/N,
    C>N (contradiction).

无聊的数学部分

我认为混淆的根源是等号登录O(f(x))=O(N)并不意味着平等!通常如果x = y则y = x。但是请考虑O(x)=O(x^2)这是真的,但反向是假的:O(x^2) != O(x)

O(f(x))是函数增长速度的上限。 上限不是确切的值。

如果g(x)=x是某个函数f(x)的上限,那么函数2*g(x)(通常情况下,任何增长速度都快于g(x))也是f(x)的上限。 {1}}。

正式定义是:如果您选择任何常量f(x),则函数g(x)将被其他函数C约束,从某些x_0开始{{1}始终大于g(x)

f(x)f(x)=N+N/2相同。如果我们采用3*N/2=1.5*N而我们的常数g(x)=NC=2的增长速度超过2*g(x)=2*N

如果1.5*NC=2,那么任何x_0=1 n>(x_0=1)

同样适用于N + log(N):

2*N > 1.5*N

对任何C*N>N+log(N) C>(N+logN)/N C>1+log(N)/N ...take n_0=2 C>1+1/2 C>3/2=1.5 使用C=22*N>N+log(N), e.g。

N>(n_0=2)

现在有趣的部分是:2*3>3+log(3), 6>3+1.58=4.68 ... 2*100>100+log(100), 200>100+6.64 ... &amp; N。例如。 N^2增长速度超过N squared

N

显然不存在大于变量的单个常量。想象一下这样一个常数C*N > N^2 C > N^2/N C > N 。然后从C=C_0函数N开始大于常量N=C_0+1,因此不存在这样的常量。

为什么这在计算机科学中很有用?

在大多数情况下,计算精确的算法时间或空间没有意义,因为它取决于硬件速度,语言开销,算法实现细节和许多其他因素。

C符号提供了估算哪种算法更好地独立于现实世界并发症的方法。很容易看出,O(N)优于O(N ^ 2),从某些Big O开始,无论两个函数前面有哪些常数。

另一个好处是能够通过浏览程序和使用n_0属性来估算算法的复杂性:

Big O

具有for x in range(N): sub-calc with O(C)

的复杂性
O(N)

仍然具有for x in range(N): sub-calc with O(C_0) sub-calc with O(C_1) 的复杂性,因为“乘以常数规则”。

O(N)

“{产品规则”的复杂性为for x in range(N): sub-calc with O(N)

O(N*N)=O(N^2)

具有for x in range(N): sub-calc with O(C_0) for y in range(N): sub-calc with O(C_1) 复杂度的“定义(只需要O(N+N)=O(2*N)=O(N))”。

C=2*C_original

具有for x in range(N): sub-calc with O(C) for x in range(N): sub-calc with O(N) 的复杂性,因为“如果O(N^2)是其他函数的总和,则增长最快的术语将确定O(f(x))”(参见数学部分中的说明)。

最后的话

f(x)比我在这里写的要多得多!例如,在某些现实世界的应用程序和算法中,有用的Big-O可能非常大,以至于复杂性较差的算法在实际数据上运行得更快。

CPU缓存可能会在其他渐近良好的算法中引入意外的隐藏因素。

等等...