为什么这段代码中的时间复杂度为O(n)而不是O(n ^ 2)?

时间:2018-07-03 22:35:26

标签: c loops time-complexity big-o complexity-theory

为什么时间复杂度不是O(n ^ 2),而是O(n)? 第一个循环不是n次,第二个循环也一样,所以变成O(n*n),这是怎么回事?

void f(int n){

     for( ; n>0; n/=2){
         int i;
         for(i=0; i<n; i++){
             printf("hey");
         }
     }
}

1 个答案:

答案 0 :(得分:6)

  

第一个循环不是n次,第二个循环也一样,所以变成O(n*n)

上述陈述为假,因为:

  1. 外部循环没有运行n次。 (外部循环运行O(log n)次,但在这种情况下没有关系。)
  2. 对于内部循环,循环次数会随着n的值的变化而变化。

要获取此代码的时间复杂度,我们应该计算内部循环主体执行的总次数。

  1. 很明显,对于n的每个值,内部循环的主体执行了n次。
  2. n的值由外部循环的for语句确定。它从函数的参数值开始,每次执行外循环主体时都减半。

因此,正如评论所指出的那样,由于n + n/2 + n/4 + n/8 + ... = 2n,该算法的时间复杂度为O(n)


对此有一些更具体的数学证明:

找到一个整数k,使2^(k-1) < n <= 2^k。为此k

  1. 内部循环总数的下限是1 + 2 + 4 + ... + 2^(k-1) = 2^k - 1 >= n - 1 ∈ Ω(n)
  2. 内部循环总数的上限是1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 < 4n - 1 ∈ O(n)

因此,内部循环的总数为Θ(n)O(n)