繁体   English   中英

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

[英]What is the most computationally efficient method to recursively calculate the Fibonacci sequence?

这是我目前的代码。

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的值。是否有更高计算效率的方法来实现这一目标?

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

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)))

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

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

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

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

这似乎memoized矫枉过正,但是让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))

无需缓存/ memoization。 这是一个Python 3实现,它将Fibonacci序列表示为矩阵的幂,然后通过减半和平方来进行有效取幂。 结果是时间和存储中的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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM