我正在计算此代码的时间复杂度,该代码打印从0到n的所有斐波那契数。根据我的计算,fib()
方法使用O(2^n)
,并且由于它被多次调用i
,因此它的结果是O(n*2^n)
。但是,这本书说它是O(2^n)
。谁能解释为什么这里的时间复杂度为O(2^n)
?
代码如下:
void allFib(int n){
for(int i = 0 ; i < n ; i++){
System.out.println(i + ": " + fib(i));
}
}
int fib(int n ){
if(n <= 0) return 0;
else if (n == 1) return 1;
return fib(n-1) + fib(n-2);
}
答案 0 :(得分:1)
我终于从教授那里得到了答案,并将其发布在这里:
根据他的说法:您不仅应该简单地查看从0到n迭代的for循环,还必须通过计算步骤来找出实际的计算量。
fib(1)采取2 ^ 1步
fib(2)需2 ^ 2步
fib(3)进行2 ^ 3步
..........
fib(n)需要2 ^ n步
现在添加这些:
2 ^ 1 + 2 ^ 2 + 2 ^ 3 + ........ + 2 ^ n = 2 ^ n + 1
不考虑常量,它是2 ^ n,因此时间复杂度是O(2 ^ n)。
答案 1 :(得分:1)
我已经想出了自己的方式来理解这本书的解决方案,希望它能对仍在挣扎中的人们有所帮助。
想象一下,我们现在称为allFib(n)。
由于我们有一个从0到n的for循环,因此将调用以下函数:
如前所述,fib(n)将采取O(2 ^ n)= 2 ^ n步 因此,
因此,allFib(n)的运行时间将为
2 ^ 0 + 2 ^ 1 + 2 ^ 2 + ... + 2 ^(n-1)。 *
按照sum of powers of 2 formula进行操作,
*
= 2 ^(n-1 + 1)-1 = 2 ^ n-1。
因此它是O(2 ^ n)
答案 2 :(得分:0)
我认为最好的思考方法是举一个例子。
我们知道fib()的运行时间大约是O(2 ^ n),从直觉上看,我们认为allFib()的运行时间为O(n * 2 ^ n),如书中所述。但这不是事实,这就是原因。
为什么O(n * 2 ^ n)是错误的:
如果我们将3代入n,则得到3 * 2 ^ 3,等于2 ^ 3 + 2 ^ 3 + 2 ^ 3。这显然是错误的,因为通过查看代码,我们知道第一个循环运行2 ^ 1,第二个循环运行2 ^ 2,第三个循环运行2 ^ 3次。因此应该是2 ^ 1 + 2 ^ 2 + 2 ^ 3。
我们如何获得O(2 ^ n):
如果我们说n = 3,则我们知道合计的功为2 ^ 1 + 2 ^ 2 + 2 ^ 3,这大约等于2 ^ 4(请参阅《两方的和》中的第630页“以了解原因),因此您可以说完成的工作量为2 ^ n + 1,但是我们删除了大O的所有常量,因此剩下2 ^ n。