我有这个功能,想知道时间的复杂性:
int f2(int n) {
if(n<2) return 1;
return f2(n/2)+f2(n-2);
}
我使用伸缩展开法计算其运行时间为O(n 2 )。这是对的吗?
编辑:重新考虑之后,我发现此函数与mergesort具有相似的结构,其具有复杂度Θ(n log n)。这是对的吗?
答案 0 :(得分:3)
假设它是n中的多项式,即某些常数a
和b
的运行时间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中呈指数,即对于某些常数a
和b
,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
这是斐波那契的顺序复杂性。你的功能结构是类似的。