具有递归调用f(n / 2)和f(n - 2)的函数的时间复杂度?

时间:2013-09-17 17:06:58

标签: c big-o time-complexity

我有这个功能,想知道时间的复杂性:

int f2(int n) {
    if(n<2) return 1;
    return f2(n/2)+f2(n-2);
}

我使用伸缩展开法计算其运行时间为O(n 2 )。这是对的吗?

编辑:重新考虑之后,我发现此函数与mergesort具有相似的结构,其具有复杂度Θ(n log n)。这是对的吗?

5 个答案:

答案 0 :(得分:3)

假设它是n中的多项式,即某些常数ab的运行时间T(n)最多为* n b 。然后,我们有:

T(n) = T(n/2) + T(n-2)
     = a*(n/2)^b + a*(n-2)^b
     = a/2^b * n^b + a*n^b + (lower-order terms)
     = a*n^b * (1/2^b + 1) + (lower-order terms)

(lower-order terms)n提升到权力的总和差异严重低于b。对于足够大的n,a * n b *(1/2 b + 1)项将主导低阶项,并且总是大于a * n b ,因此任何常数b的T(n)都不是O(n b )。

现在假设它在n中呈指数,即对于某些常数ab,T(n)最多为a * b n 。然后:

T(n) = T(n/2) + T(n-2)
     = a*b^(n/2) + a*b^(n-2)
     = a*b^n * (b^(-n/2) + 1/b^2)

现在,如果b> 1和n> = -2 log(1 - 1 / b 2 )/ log(b),然后:

n >= -2 log(1 - 1/b^2) / log(b)
-n/2 <= log(1 - 1/b^2) / log(b) = log_b(1 - 1/b^2)
b^(-n/2) <= 1 - 1/b^2
b^(-n/2) + 1/b^2 <= 1
T(n) = a*b^n * (b^(-n/2) + 1/b^2) <= a*b^n * 1 = a*b^n

因此,对于任何一个&gt; 0和b>在图1中,存在N(等于-2log(1-1 / b 2 )/ log(b)),使得对于所有n> = N,T(n)<= A * b ^ N

那说这是什么意思? T(n)不仅仅是多项式(对于任何多项式;它还包括多对数函数,例如任何多对数函数是o(更大的非对数多项式)),但T(n)小于任何指数。我不确定是否有一个简单的公式来确定结果,但这些是有用的界限。

修改

正如nhahtdh所指出的,这使得运行时间称为quasi-polynomial time

答案 1 :(得分:0)

我认为这是O(2^sqrt(n))

你有T(n) = T(n/2) + T(n-2)

插入解决方案,除以2^sqrt(n),并给出n → ∞

2^sqrt(n) = 2^sqrt(n/2)  +  2^sqrt(n-2)
---------   -----------     -----------
2^sqrt(n)    2^sqrt(n)       2^sqrt(n)

1 = 2^sqrt(-n/2) + 1

2^sqrt(-n/2) → 0

答案 2 :(得分:0)

T(n)= T(n / 2)+ T(n-2)+ 1

我们知道T(n-2)> T(N / 2)

我们可以这样说:

T(n)= 2T(n-2)+ 1

因此T(n-2)= 2T(n-4)+ 1

T(n)= 4T(n-4)+ 2

T(n)= 8T(n-6)+ 3

T(n)=(2 ^ k)T(n-2k)+ k

因为我们知道T(1)= 1

然后n-2k = 1 - > k =(n-1)/ 2

T(n)= 2 ^((n-1)/ 2)T(1)+(n-1)/ 2

T(n)= 2 ^((n-1)/ 2)+(n-1)/ 2

T(n)= 2 ^((n-1)/ 2)

但必须有更好的解决方案。

答案 3 :(得分:0)

始终存在经验方法 - 时间......

#include "timer.h"
#include <stdio.h>

static
int f2(int n)
{
    if (n < 2)
        return 1;
    return f2(n/2) + f2(n-2);
}

int main(void)
{

    printf("Fast:\n");
    for (int i = 1; i <= 512; i *= 2)
    {
        Clock clk;
        clk_init(&clk);
        clk_start(&clk);
        long sum = 0;
        for (int j = 0; j < 100; j++)
            sum += f2(i);
        clk_stop(&clk);
        char buffer[32];
        printf("%8d: elapsed %10s s; sum = %12ld\n",
               i, clk_elapsed_us(&clk, buffer, sizeof(buffer)), sum/100);
    }

    printf("\nSlow:\n");
    for (int i = 512; i < 1024; i += 16)
    {
        Clock clk;
        clk_init(&clk);
        clk_start(&clk);
        long sum = 0;
        for (int j = 0; j < 100; j++)
            sum += f2(i);
        clk_stop(&clk);
        char buffer[32];
        printf("%8d: elapsed %7s s; sum = %12ld\n",
               i, clk_elapsed_ms(&clk, buffer, sizeof(buffer)), sum/100);
    }

    return 0;
}

结果:

为了记录,该测试是在运行Mac OS X 10.8.5的MacBook Pro,2.3 GHz的Intel Core i7和16 GiB RAM上运行的。

Fast:
       1: elapsed   0.000000 s; sum =            1
       2: elapsed   0.000001 s; sum =            2
       4: elapsed   0.000001 s; sum =            4
       8: elapsed   0.000002 s; sum =           10
      16: elapsed   0.000008 s; sum =           36
      32: elapsed   0.000045 s; sum =          202
      64: elapsed   0.000408 s; sum =         1828
     128: elapsed   0.005985 s; sum =        27338
     256: elapsed   0.139971 s; sum =       692004
     512: elapsed   5.273834 s; sum =     30251722

Slow:
     512: elapsed   5.286 s; sum =     30251722
     528: elapsed   6.370 s; sum =     36243644
     544: elapsed   7.609 s; sum =     43234278
     560: elapsed   8.949 s; sum =     51361196
     576: elapsed  10.397 s; sum =     60777212
     592: elapsed  12.171 s; sum =     71651844
     608: elapsed  14.394 s; sum =     84172786
     624: elapsed  16.716 s; sum =     98547380
     640: elapsed  19.176 s; sum =    115004102
     656: elapsed  21.985 s; sum =    133794468
     672: elapsed  25.295 s; sum =    155194954
     688: elapsed  29.170 s; sum =    179508916
     704: elapsed  33.456 s; sum =    207068524
     720: elapsed  38.317 s; sum =    238237116
     736: elapsed  43.776 s; sum =    273411566
     752: elapsed  49.878 s; sum =    313024652
     768: elapsed  56.979 s; sum =    357547444
     784: elapsed  64.456 s; sum =    407492292
     800: elapsed  72.980 s; sum =    463415834
     816: elapsed  82.535 s; sum =    525922004
     832: elapsed  93.062 s; sum =    595665060
     848: elapsed 104.886 s; sum =    673353212
     864: elapsed 118.038 s; sum =    759752270
     880: elapsed 132.569 s; sum =    855689292
     896: elapsed 150.487 s; sum =    962056258
     912: elapsed 166.065 s; sum =   1079814524
     928: elapsed 185.616 s; sum =   1209999302
     944: elapsed 206.875 s; sum =   1353724140
     960: elapsed 230.670 s; sum =   1512185428
     976: elapsed 256.718 s; sum =   1686667684
     992: elapsed 285.158 s; sum =   1878548866
    1008: elapsed 316.281 s; sum =   2089305684

我没有对这些数据进行曲线拟合。显然,您可以减少或消除较大尺寸的迭代,依此类推等等(这样可以避免1024出现溢出,并且......)。

如果有人在绘制图形方面有一些专业知识,它可能会显示结果(当时的对数标度)。

答案 4 :(得分:-1)

我认为这是指数级的。为什么?每个f(n)导致调用f(n / 2)和f(n-2)。

查看此问题以获取详细信息:

Computational complexity of Fibonacci Sequence

这是斐波那契的顺序复杂性。你的功能结构是类似的。