【问题标题】:Why is the time complexity O(n) instead of O(n^2) in this code?为什么这段代码的时间复杂度是 O(n) 而不是 O(n^2)?
【发布时间】:2018-07-03 22:35:26
【问题描述】:

为什么这里的时间复杂度不是 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");
         }
     }
}

【问题讨论】:

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


【解决方案1】:

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

以上陈述是错误的,因为:

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

为了得到这段代码的时间复杂度,我们应该计算内部循环体被执行的总次数。

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

所以正如 cmets 已经说过的,由于n + n/2 + n/4 + n/8 + ... = 2n,这个算法的时间复杂度是O(n)。


关于这方面的一些更具体的数学证明:

找到一个整数k,使得2^(k-1) &lt; n &lt;= 2^k。对于这个k:

  1. 内部循环总数的下限是1 + 2 + 4 + ... + 2^(k-1) = 2^k - 1 &gt;= n - 1 ∈ Ω(n)。
  2. 内部循环总数的上限是1 + 2 + 4 + ... + 2^k = 2^(k+1) - 1 &lt; 4n - 1 ∈ O(n)。

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

【讨论】:

    猜你喜欢
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 2023-04-07
    • 2021-08-13
    • 1970-01-01
    • 2020-03-22
    • 1970-01-01
    相关资源
    最近更新 更多