我知道大o符号,但我不知道如何计算它的许多函数。特别是,我一直在试图弄清楚朴素版斐波那契数列的计算复杂度:
int Fibonacci(int n)
{
if (n <= 1)
return n;
else
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
斐波那契数列的计算复杂度是多少?它是如何计算的?
我知道大o符号,但我不知道如何计算它的许多函数。特别是,我一直在试图弄清楚朴素版斐波那契数列的计算复杂度:
int Fibonacci(int n)
{
if (n <= 1)
return n;
else
return Fibonacci(n - 1) + Fibonacci(n - 2);
}
斐波那契数列的计算复杂度是多少?它是如何计算的?
当前回答
只要问问自己,F(n)需要执行多少条语句才能完成。
对于F(1),答案是1(条件的第一部分)。
对于F(n)答案是F(n-1) + F(n-2)
那么什么函数满足这些规则呢?试试an (a > 1):
==地理==根据美国人口普查,该镇总面积为,其中土地和(1.1%)水。
再除以a(n-2)
A2 == a + 1
解出a,你得到(1+根号(5))/2 = 1.6180339887,也就是黄金比例。
所以需要指数级的时间。
其他回答
你可以展开它,有一个可视化
T(n) = T(n-1) + T(n-2) <
T(n-1) + T(n-1)
= 2*T(n-1)
= 2*2*T(n-2)
= 2*2*2*T(n-3)
....
= 2^i*T(n-i)
...
==> O(2^n)
它的下端以2^(n/2)为界,上端以2^n为界(如其他注释中所述)。这个递归实现的一个有趣的事实是它本身有一个紧密的Fib(n)渐近界。这些事实可以总结为:
T(n) = Ω(2^(n/2)) (lower bound)
T(n) = O(2^n) (upper bound)
T(n) = Θ(Fib(n)) (tight bound)
如果你愿意,可以用它的封闭形式进一步简化紧边界。
我同意pgaur和rickerbh的观点,递归-fibonacci的复杂度是O(2^n)。
我通过一个相当简单但我相信仍然有效的推理得出了同样的结论。
首先,这完全是关于计算第n个斐波那契数时调用多少次递归斐波那契函数(F()从现在开始)。如果它在0到n的数列中被调用一次,那么我们有O(n),如果它对每个数字被调用n次,那么我们得到O(n*n)或O(n²),以此类推。
因此,当对一个数字n调用F()时,对一个给定的0到n-1之间的数字调用F()的次数随着趋近于0而增加。
作为第一印象,在我看来,如果我们把它放在视觉上,每次绘制一个单位F()被调用为给定的数字,我们会得到一种金字塔形状(也就是说,如果我们将单位水平居中)。就像这样:
n *
n-1 **
n-2 ****
...
2 ***********
1 ******************
0 ***************************
现在的问题是,随着n的增长,金字塔的底部扩大的有多快?
让我们举一个真实的例子,比如F(6)
F(6) * <-- only once
F(5) * <-- only once too
F(4) **
F(3) ****
F(2) ********
F(1) **************** <-- 16
F(0) ******************************** <-- 32
我们看到F(0)被调用了32次,也就是2^5,在这个例子中是2^(n-1)
现在,我们想知道F(x)被调用了多少次,我们可以看到F(0)被调用的次数只是其中的一部分。
如果我们在心里把F(6)到F(2)线的所有*移到F(1)线中,我们看到F(1)和F(0)线现在长度相等。这意味着,当n=6 = 2x32=64=2^6时,total乘以F()被调用。
现在,说到复杂性:
O( F(6) ) = O(2^6)
O( F(n) ) = O(2^n)
好吧,根据我的说法,它是O(2^n),因为在这个函数中,只有递归花费了相当多的时间(分治)。我们看到,上面的函数将在树中继续存在,直到叶子趋近于F(n-(n-1))级,即F(1)。因此,当我们在这里记下树的每个深度处遇到的时间复杂度时,求和级数为:
1+2+4+.......(n-1)
= 1((2^n)-1)/(2-1)
=2^n -1
它是2^n的O(2^n)阶。
在麻省理工学院有一个关于这个具体问题的很好的讨论。在第5页,他们指出,如果你假设一个加法需要一个计算单位,那么计算Fib(N)所需的时间与Fib(N)的结果密切相关。
因此,你可以直接跳到斐波那契数列的非常接近的近似:
Fib(N) = (1/sqrt(5)) * 1.618^(N+1) (approximately)
因此,假设朴素算法的最坏情况是
O((1/sqrt(5)) * 1.618^(N+1)) = O(1.618^(N+1))
PS:如果你想了解更多信息,维基百科上有关于第n个斐波那契数的封闭形式表达的讨论。