使用O(1)空间在python中自下而上的斐波那契

时间:2016-04-29 21:59:51

标签: python recursion fibonacci

我想用O(1)空间写一个自下而上的斐波那契。我的问题是python的递归栈限制我测试大数。有人可以为我提供替代或优化吗?这是我的代码:

def fib_in_place(n):
    def fibo(f2, f1, i):
        if i < 1:
            return f2
        else:
            return fibo(f1, f2+f1, i -1)
    return fibo(0, 1, n)

4 个答案:

答案 0 :(得分:4)

你可以记住Fibonacci函数的效率,但如果你需要一个递归函数,它仍然至少需要O(n):

def mem_fib(n, _cache={}):
    '''efficiently memoized recursive function, returns a Fibonacci number'''
    if n in _cache:
        return _cache[n]
    elif n > 1:
        return _cache.setdefault(n, mem_fib(n-1) + mem_fib(n-2))
    return n

这是我对Python中主要Fibonacci问题的回答:How to write the Fibonacci Sequence in Python

如果允许使用迭代而不是递归,则应该这样做:

def fib():
    a, b = 0, 1
    while True:            # First iteration:
        yield a            # yield 0 to start with and then
        a, b = b, a + b    # a will now be 1, and b will also be 1, (0 + 1)

用法:

>>> list(zip(range(10), fib()))
[(0, 0), (1, 1), (2, 1), (3, 2), (4, 3), (5, 5), (6, 8), (7, 13), (8, 21), (9, 34)]

如果您只想获得第n个号码:

def get_fib(n):
    fib_gen = fib()
    for _ in range(n):
        next(fib_gen)
    return next(fib_gen)

和用法

>>> get_fib(10)
55

答案 1 :(得分:4)

使用递归这种方式意味着你正在使用O(N)空间,而不是O(1) - O(N)在堆栈中。

为什么要使用递归?

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b

    return a

答案 2 :(得分:1)

为什么要使用迭代?

def fib(n):
    phi_1 = (math.sqrt(5) + 1) / 2
    phi_2 = (math.sqrt(5) - 1) / 2
    f = (phi_1**n - phi_2**n) / math.sqrt(5)
    return round(f)

代数结果是准确的; round 操作只是为了允许数字表示不准确。

答案 3 :(得分:0)

尾递归定义很容易变成迭代定义。如有必要,请翻转条件,以便尾递归调用位于“if”分支中。

def fibo(f2, f1, i):
    if i > 0:
        return fibo(f1, f2+f1, i -1)
    else:
        return f2

然后将'if'变为'while',将return替换为新参数的解包赋值,并(可选)删除'else'。

def fibo(f2, f1, i):
    while i > 0:
        f2, f1, i = f1, f2+f1, i -1
    return f2

通过迭代,您不需要嵌套定义。

def fib_efficient(n):
    if n < 0:
        raise ValueError('fib argument n cannot be negative')
    new, old = 0, 1
    while n:
        new, old = old, old+new
        n -= 1
    return new

本地名称“新”和“旧”是指斐波纳契使用生物繁殖来激发序列。然而,这个故事更适合酵母细胞而不是兔子。老的,成熟的酵母细胞通过萌发新的未成熟细胞而繁殖。 (印度的这个功能的原始来源似乎是Virahanka计算这个数字的方法,从一个有序的1和2节奏音节序列中制作出具有n节拍的梵文诗意线。)