包含另一个功能的功能的时间复杂度

时间:2018-08-29 11:37:36

标签: for-loop time while-loop complexity-theory

有人可以仔细解释一下我如何弄清楚这段代码的时间复杂度吗?

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;
}

谢谢!

3 个答案:

答案 0 :(得分:1)

一种更具体的证明结果的方法:

如先前的正确回答所述,g(n)的复杂度为O(log n)g(n)中的循环执行的准确次数为floor(log2(n)) + 1

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

enter image description here

由此,使用循环条件f(n),此循环执行的次数为:

enter image description here

这使人们可以将(*)的复杂度函数表示为求和:

enter image description here

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

n中带下划线的项的幂为2。当O(log n + log log n) = O(log n)趋于无穷大时,该项消失,因此带下划线的项本身收敛为2。

由于第一项占主导地位,因此最终的复杂度仅为 void change(int** ptr) { **ptr = 50; *ptr = nullptr; } void change(int*& ptr) { *ptr = 50; ptr = nullptr; } int main() { int a = 5; int* ptr = &a; int** ptr2 = &ptr; std::cout << "value: " << a << std::endl; std::cout << "value: " << ptr << std::endl; std::cout << "value: " << ptr2 << std::endl; change(ptr2); //change(ptr); std::cout << "value: " << a << std::endl; std::cout << "value: " << ptr << std::endl; std::cout << "value: " << ptr2 << std::endl; system("pause"); }

答案 1 :(得分:0)

g的对数是对数的(如果您将其传递给n,则其循环将重复log[2](n)次,因为它将i的倍数加倍为到达n

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

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

编辑:

  

但是正确的答案是O(log(n))(最终测试答案),我不明白为什么。...

正如我所说的:

  

如果我们准确分析g的重复次数如何随着f的进行而减少,我们会找到一个更好的限制

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

或者您可能会注意到,在f的第一个迭代中,将有g的许多迭代,与之相比,g的所有其他调用都不相关(对数地消失)。由于g的第一次调用是O(log(n))`,因此我们可以在此处截断它并说这就是复杂性。

答案 2 :(得分:-1)

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

例如,当分析某种算法时,可能会发现完成大小为n的问题所花费的时间(或步数)是由

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

如果我们忽略常量(这是有意义的,因为它们取决于程序所运行的特定硬件)和增长较慢的术语,我们可以说“ T(n)”以n ^ 2的顺序增长并写: T(n)= O(n ^ 2)

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

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

(或者f(x)= O(g(x)),对于x->无限更精确),并且仅当存在常量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表示法在值非常大时给出了一个假设   将运行n次,而内部循环运行n次

     

假设n-> 100大于总n ^ 2 10000次运行时间