包含另一个函数的函数的时间复杂度

Time Complexity of function that contains another function

谁能详细解释一下这段代码的时间复杂度怎么算?

int f(int n)
{
    int sum = 0;
    while (n>1)
    {
        sum +=g(n)
        n = sqrt(n)
    }
    return sum;
}

其中 g(n) 由下式给出:

int g(int n)
{
    int sum  = 0;
    for (int i = 1; i<n; i*=2)
        sum +=i;
    return sum;
}

提前致谢!

g 是它的参数的对数(如果你传递它 n,它的循环重复 log[2](n) 次,因为它需要多次迭代才能使 i 达到 n.

f 是双对数 - 它在每个操作中将 n 指数 减半,重复 log[2](log[2](n))

我们可以忽略 g 是一个单独的函数这一事实 - 实际上,它是一个嵌套在另一个循环中的循环。如果我们准确分析 g 的重复次数如何随着 f 的进行而减少,我们可以找到更好的限制,但是 O(log n * log log n) 已经足够好了。 (复杂性理论就像海鲜:虽然 "I ate bluefin tuna" 可能是 正确答案,但 "I ate fish" 并没有错。)

编辑:

However the right answer is O(log(n)) (final test answer) and I don't understand why....

正如我所说:

We can find a better limit if we analyse exactly how the number of repetitions of g decreases as f progresses

但老实说,从结果比代码更容易做到这一点。假设 n 从 65536 开始。这将为我们提供 g 的 16 次迭代。它的根是 256,这将允许 g 到 运行 8 次。接下来是 16,g 的 4 次迭代。然后4为2,2为1。这看起来像一个几何级数:16+8+4+2+1 = 32-1,其中322 * log[2](65536),符合O(log n)。

或者您可能会注意到在 f 的第一次迭代中会有很多 g 的迭代,与之相比 g 的所有其他调用都是无关紧要的(以对数方式消失)。由于 g 的第一次调用是 O(log(n))`,我们可以在那里 t运行 并说这就是复杂性。

稍微具体一点的证明方法:

正如之前正确回答的那样,g(n) 的复杂度是 O(log n)g(n) 中的循环执行的精确次数是 floor(log2(n)) + 1.

现在 f(n)。在第 m 次循环迭代后 n 的值,相对于 n 原始 值,是:

由此,使用循环条件n > 1,本次循环执行的次数为:

这样可以将 f(n) 的复杂度函数表示为求和:

(*) 中,我使用了这样一个事实,即向下舍入的数字与其原始值仅相差 小于 而不是 1(因此 O(1))。在 (**) 中,我使用了几何级数和的标准结果。

(**)中划线项的2的负次方。当n趋于无穷大时,此项消失,所以划线项本身收敛于2。

因此最终的复杂度仅为 O(log n + log log n) = O(log n),因为第一项占主导地位。

描述函数渐近行为的大 O 符号。基本上,它告诉您函数增长或下降的速度

例如,在分析某些算法时,可能会发现完成大小为 n 的问题所需的时间(或步数)由

给出
T(n) = 4 n^2 - 2 n + 2

如果我们忽略常量(这是有道理的,因为它们取决于程序 运行 所在的特定硬件)和增长较慢的项,我们可以说 "T(n)" 以 n^ 的顺序增长2 " 和 write:T(n) = O(n^2)

对于正式定义,假设f(x) 和g(x) 是定义在实数的某个子集上的两个函数。我们写

f(x) = O(g(x))

(或 f(x) = O(g(x)) for x -> infinity 更精确)当且仅当存在常数 N 和 C 使得

|f(x)| <= C|g(x)| for all x>N

直觉上,这意味着 f 的增长速度并不比 g

如果a是实数,我们写

f(x) = O(g(x)) for x->a

当且仅当存在常数 d > 0 和 C 使得

|f(x)| <= C|g(x)| for all x with |x-a| < d

所以你的情况是

O(n) as |f(x)| > C|g(x)|

引用自http://web.mit.edu/16.070/www/lecture/big_o.pdf

for r from 0 to xlist:  // --> n time
       for c from 0 to ylist: // n time
         sum+= values[r][c]  
         n+1

}

Big O Notation gives an assumption when value is very big outer loop will run n times and inner loop is running n times

Assume n -> 100 than total n^2 10000 run times