递归计算Fibonacci序列的计算效率最高的方法是什么?

时间:2017-10-05 15:24:28

标签: python recursion fibonacci

以下是我目前的代码。

def fibonacci(n):

    if n == 1:
        return 1
    elif n == 2:
        return 1
    else:
        value = fibonacci(n - 1) + fibonacci(n - 2)
        return value

目前计算大于n = 30的值需要相当长的时间。是否有更高计算效率的方法来实现这一目标?

4 个答案:

答案 0 :(得分:3)

添加值缓存以交换一些内存以减少处理时间可能是一种有用的方法。纯递归程序将尝试反复计算值,但是这需要较长时间的值。如果值没有改变,那么存储它们会很有帮助。然而,重要的是要注意,如果值是易变的,则可能需要不同的方法。

fibonacci_value_cache = {}


def fibonacci(n):

    if n == 1:
        return 1
    elif n == 2:
        return 1
    elif n in fibonacci_value_cache:
        return fibonacci_value_cache[n]
    else:
        fibonacci_value_cache[n] = fibonacci(n - 1) + fibonacci(n - 2)
        return fibonacci_value_cache[n]

n = 100

print("Fib " + str(n) + ": " + str(fibonacci(n)))

在这里,我们检查值是否在字典中,如果是,则返回它,否则我们计算它并将其添加到字典中。这意味着我们不会多次计算相同的值,从而更好地利用处理器。

答案 1 :(得分:0)

使用动态编程的思想,并存储中间结果以节省计算成本,它可能非常有效。对于笔记本电脑上的 0.02s ,以下代码的费用低于 n=10000

def fib(n):  # return Fibonacci series up to n
    result = []
    a, b = 0, 1
    for i in range(n):
        result.append(b)
        a, b = b, a + b
    return result

答案 2 :(得分:0)

有一个装饰器的配方,它以你想要的为例。它在Memoize中命名为PythonDecoratorLibrary

看起来有点矫枉过正,但让memoized装饰器围绕它可能对其他未来的任务有用。也就是说,这里完全是这样的(尽管我最后更改了print):

import collections
import functools

class memoized(object):
   '''Decorator. Caches a function's return value each time it is called.
   If called later with the same arguments, the cached value is returned
   (not reevaluated).
   '''
   def __init__(self, func):
      self.func = func
      self.cache = {}
   def __call__(self, *args):
      if not isinstance(args, collections.Hashable):
         # uncacheable. a list, for instance.
         # better to not cache than blow up.
         return self.func(*args)
      if args in self.cache:
         return self.cache[args]
      else:
         value = self.func(*args)
         self.cache[args] = value
         return value
   def __repr__(self):
      '''Return the function's docstring.'''
      return self.func.__doc__
   def __get__(self, obj, objtype):
      '''Support instance methods.'''
      return functools.partial(self.__call__, obj)

@memoized
def fibonacci(n):
   "Return the nth fibonacci number."
   if n in (0, 1):
      return n
   return fibonacci(n-1) + fibonacci(n-2)

print(fibonacci(12))

答案 3 :(得分:0)

无需缓存/记忆。这是一个表达Fibonacci sequence as powers of a matrix的Python 3实现,然后通过减半和平方来进行有效取幂。结果是时间和存储都是O(log n)。

def matrix_fib(n):
    if n == 1:
        return [0,1]
    else:
        f = matrix_fib(n // 2)
        c = f[0] * f[0] + f[1] * f[1]
        d = f[1] * (f[1] + 2 * f[0])
        return [c,d] if (n & 1) == 0 else [d,c+d]

def fib(n):
  return n if n == 0 else matrix_fib(n)[1]

print(fib(1000000))

在我的笔记本电脑上,这会在超过半秒的时间内咳出百万分之一的斐波那契数值,其中很大一部分可能是大整数算术和输出格式化 - 结果非常大。但是,您不必担心堆栈溢出。调用堆栈深度仅为log2(1000000)= 20。