下面的代码块的时间复杂度是多少 无效函数(int n)。
我的尝试是,最外层的循环将运行n / 2次,而内层的两个将运行2 ^ q次。然后我用n等于2 ^ q并以2为底得到q为1/2(log n)。乘以时间复杂度,我得到的值为O(nlog(n)),而答案是O(nlog ^ 2(n) ))。
void function(int n) {
int count = 0;
for (int i=n/2; i<=n; i++)
for (int j=1; j<=n; j = 2 * j)
for (int k=1; k<=n; k = k * 2)
count++;
}
答案 0 :(得分:6)
是时候应用理解循环嵌套的黄金法则了:
如有疑问,请由内而外!
让我们从原始的循环巢开始吧:
for (int i=n/2; i<=n; i++)
for (int j=1; j<=n; j = 2 * j)
for (int k=1; k<=n; k = k * 2)
count++;
该内部循环将运行Θ(log n)次,因为在该循环的m次迭代之后,我们看到k = 2 m ,并且当k≥n = 2 lg n时停止。因此,我们用以下更简单的表达式替换该内部循环:
for (int i=n/2; i<=n; i++)
for (int j=1; j<=n; j = 2 * j)
do Theta(log n) work;
现在,看看最里面的剩余循环。通过与之前完全相同的推理,我们看到此循环也运行Θ(log n)次。由于我们进行了每次都进行Θ(log n)迭代的Θ(log n)迭代,因此我们看到可以用以下更简单的循环代替此循环:
for (int i=n/2; i<=n; i++)
do Theta(log^2 n) work;
在这里,外循环运行Θ(n)次,因此总体运行时间为Θ(n log 2 n)。
我认为,根据您在问题中所说的话,您具有正确的见解,但只是忘记将对数项的两个副本相乘,两个内环各一个。
答案 1 :(得分:2)
您的代码中有3
个嵌套循环。
n/2
次,在计算复杂度时几乎等于n。logn
次。logn
次。因此,最终时间复杂度将为O( n * logn * logn ) == O(nlog^2n)
。
现在,您可能想知道如何记录两个内部循环的运行时复杂度。可以概括如下:
由于我们在每次迭代中都乘以2
,因此我们需要q的值如下:
n = 2 ^ q
。
两边都采用日志基础2
log2 n = log2 (2^q) log2 n = q log2(2) log2 n = q * 1 [ since, log2(2) is 1 ]
因此,q
等于logn
。
因此,总体时间复杂度为:O(n*log^2n).
答案 2 :(得分:1)
第一个循环需要:n / 2
第二个循环:log(n)
第三循环:log(n)
请注意,由于内部循环的步数乘以2,因此在时间复杂度方面,它们各自的计数器呈指数增长,在n
中达到log(n)
。
然后,还请注意,在这种情况下,可以安全地忽略诸如1/2的常量,其结果为O(n * log(n) *log(n))
,因此:
O(nlog 2 n)