递归函数运行时间分析

时间:2013-11-25 01:24:47

标签: python loops recursion

我正在努力找出这个递归函数中n为10,000的运算时间:

def fib3(n):
    if n<3:
        return 1
    else:
        return fib3(n-1) + fib3(n-2) + fib3(n-3)

我理解循环中很容易说出运行时间是什么 - 它是循环的数量,但我们如何在递归中执行此操作?

3 个答案:

答案 0 :(得分:1)

如果您按照这样设置代码

from collections import Counter
c = Counter()
def fib3(n):
    c[n] += 1
    if n < 9980:
        return 1
    else:
        return fib3(n-1) + fib3(n-2) + fib3(n-3)

fib3(10000)
print c

你会得到这样的结果

Counter({9979: 223317, 9978: 187427, 9977: 121415, 9980: 121415, 9981: 66012, 9982: 35890, 9983: 19513, 9984: 10609, 9985: 5768, 9986: 3136, 9987: 1705, 9988: 927, 9989: 504, 9990: 274, 9991: 149, 9992: 81, 9993: 44, 9994: 24, 9995: 13, 9996: 7, 9997: 4, 9998: 2, 9999: 1, 10000: 1})

忽略小于9980的键的值,您已经可以看到,n每个n的通话次数大约翻倍

所以你可以估计复杂度为O(2 n )(它实际上是关于 O(1.839 n ))

如果你想计算确切的通话次数,你应该尝试写一个递归函数,比如fib3_count(n),它返回计算fib3(n)所需的通话次数

修改

计算big-O复杂度可以通过求解这个等式来完成

 x**3 - x**2 - x**1 - 1 == 0

复杂度为O(x n

等式的3个根是

x1 = 1.8392867552141612
x2 = (-0.41964337760708065+0.6062907292071992j)
x3 = (-0.41964337760708065-0.6062907292071992j)

由于x必须是实数,我们留下:O(1.8392867552141612 n

答案 1 :(得分:1)

这是指数时间。如果fib3(i)显示fib3(k)的运行速度比i < k快,则可以直接显示,因为计算fib3(k)将涉及计算fib3(i),可能需要多次。计算fib3(n+3)需要计算fib3(n+2)fib3(n+1)fib3(n);因此,它至少需要计算fib3(n)的3倍。通过归纳,您可以证明fib3(n)至少花费O(3^(n/3))时间进行计算。更复杂的分析可以给出渐近精确的界限。

答案 2 :(得分:0)

在每次递归通话中,您都会进行3次额外通话。它与二叉树非常相似,但是它们有2个子节点,完整二叉树中的子节点总数为pow(2,n)。

这里有3个流量转移,这使得O(3^n)

修改

以下是一些代码:

import math
class F:
    def __init__(self):
        self.c = 0

    def fib3(self, n):
        self.c += 1
        if n < 3:
            return 1
        else:
            return self.fib3(n-1) + self.fib3(n-2) + self.fib3(n-3)

f = F()
f.fib3(20)
print f.c   

输出将是:

128287

print math.pow(3, 20)评估为3486784401.这是高估的,但这是由于fib3可以减少3而不是1来确定。

如果您运行以下代码,并且始终在n-1上调用fib3,您将获得O(3^n)

import math
class F:
    def __init__(self):
        self.c = 0

    def fib3(self, n):

        if n < 1:
            return 1
        else:
            self.c += 1
            return self.fib3(n-1) + self.fib3(n-1) + self.fib3(n-1)

f = F()
f.fib3(10)
print f.c

实际上你会得到O((3^n) / 2),但这里有两个因素,所以它只是O(3^n)