如何计算以下算法的时间复杂度?
for(i=1;i<=n;i++)
for(k=i;k*k<=n;k++)
{
Statements;
}
据我所知,嵌套for循环的时间复杂度等于执行最里面的循环的次数。因此,这里最里面的循环执行了n*n
次,因此它是O(n^2)
。
是否取决于第二个循环中给出的条件O(n)
是k*k<=n
?
谢谢!
答案 0 :(得分:0)
算法的时间复杂度始终根据某种操作类型来衡量。例如,如果您的Statements;
具有取决于n的未知时间复杂度,那么首先描述时间复杂度会产生误导。
但是您可能想知道的是根据 Statements;
操作的时间复杂度。如果Statements;
是恒定时间操作,则这变得特别有意义。在这种情况下,我们所寻找的只是简单地计算执行Statements;
的次数。如果此数字为3 * n,则时间复杂度将为O(n)。
要回答这个问题,让我们分开您的嵌套循环。外循环从(包括)1迭代到n,因此无论发生什么事情,它将精确地运行n次。
对于外循环的每次迭代,内循环将执行一次。它从k = i开始,并迭代直到k*k > n
或k > sqrt(n)
。请注意,无论何时i > sqrt(n)
都不会运行。我们可以看到它平均可以运行
O(sqrt(n) + sqrt(n)-1 + sqrt(n)-2 + ... + 0) / n
迭代。通过求和公式,您可以找到here,它等于
O( sqrt(n) * (sqrt(n) + 1) / 2 ) = O( (n + sqrt(n))/2 ) = O( n + sqrt(n) ) = O(n)
。
是的,按照您的建议,这种情况下的时间复杂度为O(n)
。
您可以通过编写一个简单的脚本来查看实际情况,该脚本可以模拟您的算法并计算Statements;
的数量。在下面的JavaScript中,因此可以作为摘要运行:
// Simulation
function f(n) {
let res = 0;
for(let i=1;i<=n;i++)
for(let k=i;k*k<=n;k++)
++res;
return res;
}
// Estimation
function g(n) {
return ~~((n + Math.sqrt(n))/2);
}
console.log(
f(10),
f(100),
f(1000),
f(10000),
);
console.log(
g(10),
g(100),
g(1000),
g(10000),
);
希望您觉得这有用。