我们如何计算天真的斐波纳西的呼叫次数?

时间:2017-09-16 16:45:07

标签: algorithm performance recursion time-complexity exponential

所以以下不是优化的fibonacci函数:

sub fib {  
    my ( $n ) = @_;  
    return 1 if( $n == 1 || $n == 2 );  
    return fib( $n - 1 ) + fib( $n - 2 );  
}  

当我们试图找到20的斐波那契时,我实际打印了fib(3)被调用的次数。
它是2584. fib(2)被称为4181 据我所知,这个算法表现出指数行为 我的问题是如何计算fib(3)将被称为2584次实际上在代码中保留一个计数器并打印函数调用?如何计算指数部分?

3 个答案:

答案 0 :(得分:3)

fib(i)只能直接从fib(i+1)fib(i+2)调用,每次调用一次。

因此calls(i)fib(i)的来电次数)等于calls(i+1) + calls(i+2)

因此,如果我们从m开始,我们尝试计算calls(n),那么我们有以下内容:

calls(m)   = 1             (= fib(1))
calls(m-1) = 1             (= fib(2))
calls(m-2) = 2 (1+1)       (= fib(3))
calls(m-3) = 3 (1+2)       (= fib(4))
calls(m-4) = 5 (2+3)       (= fib(5))
...

这只是Fibonacci序列,我们想要计算m-n+1 - 号码 (要明白为什么它完全是m-n+1,请考虑n = m何时应该fib(1))。

calls(n) = fib(m-n+1)

我们可以在这里使用优化的Fibonacci函数来有效地(在线性时间内)计算fib(m-n+1),这将是未优化版本中fib(n)的调用次数。

对于您的示例,如果您致电fib(3)2584将被调用fib(20)次。
fib(20-3+1) = fib(18) = 2584

注意:calls(1) = calls(3)(因为fib(2)不会调用fib(1)),所以这是一个特例。

答案 1 :(得分:1)

我相信它是Target - desired number + 1处的Fibbonaci号码,因此在询问fib(3)fib(20)被调用的次数是多少时fib(20 - 3 + 1)的值{{1} (fib(18) = 2584)。

如果你抽出一张代表fibbonaci电话的树,你可以自己看看!

答案 2 :(得分:1)

Dukeling向您展示了导致fib(3)被调用多少次的序列:fib(20) (m)被调用一次,fib(19) (m-1)一次,然后fib(18)每次被调用{调用{1}}或fib(19),总计1 + 1.

当我们在查找fib(20)被调用次数的路上向下移动时,您会注意到数字(和计算)与斐波那契序列本身相对应。我们从20下降到3 m-n + 1步,每一步对应下一个Fibonacci数。当我们达到调用fib(3)(fib(n))的次数时,序列已经到达fib(3)斐波纳契数,这与m-n+1被调用的次数相对应在未经优化的递归期间。