【问题标题】:Make fibo faster [duplicate]使fibo更快[重复]
【发布时间】:2018-11-30 20:43:30
【问题描述】:

我需要编写一个代码来给出一个数字并将 F[number] 打印给我。这个代码很慢。有更快的代码的想法吗?

 while True:
      n=input()
      if n=='END' or n=='end':
         break
      class Fibonacci:
            def fibo(self, n):
                if int(n) == 0:
                   return 0
                elif int(n) == 1:
                   return 1
                else:
                  return self.fibo(int(n)-1) + self.fibo(int(n)-2)
      f=Fibonacci()
      print(f.fibo(n))

【问题讨论】:

  • 为什么是class?该声明是完全没有必要的..

标签: python fibonacci


【解决方案1】:

我在这篇文章中写了一些关于更快斐波那契的文章,也许其中一个对你有用? https://sloperium.github.io/calculating-the-last-digits-of-large-fibonacci-numbers.html

无论如何。您的代码非常慢,因为您一遍又一遍地调用相同的子树会获得指数级的运行时间。

您可以尝试线性解决方案:

def fib3(n):
    if n == 0:
        return 0
    f1 = 0
    f2 = 1

    for i in range(n-1):
        f1,f2 = f2, f1+f2
    return f2

【讨论】:

  • n -= 1 完全没有意义; range 循环使用原始的n。我猜你从基于循环的while 解决方案开始,改为for,然后没有删除n-=1
  • 你说的很对:-)
【解决方案2】:

您可以使用functools memoize 使其存储以前的值,这样就不必递归调用斐波那契函数。他们列出的例子实际上是斐波那契

【讨论】:

    【解决方案3】:

    你可以使用字典来记忆函数:

    class Fibonacci:
        memo = {}
        def fibo(self, n):
            if n in self.memo:
                return self.memo[n]
            if int(n) == 0:
                value = 0
            elif int(n) == 1:
                value = 1
            else:
                value = self.fibo(int(n) - 1) + self.fibo(int(n) - 2)
            self.memo[n] = value
            return value
    

    【讨论】:

      【解决方案4】:

      使用动态编程:这可以防止它每次都计算到 0 和 1:

      memory = {0:0, 1:1}
      def fibo(n):
          if n in memory:
              return memory[n]
          else:
              ans = fibo(int(n)-1) + fibo(int(n)-2)
              memory[n] = ans
              return ans
      

      测试:

      >>> fibo(1000)
      43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
      

      这几乎是瞬间的。

      【讨论】:

        【解决方案5】:
        1. 不要使用class;你没有从中得到任何好处
        2. 不要在每个循环中不必要地重新定义您的类
        3. str 转换为int 一次,预先,而不是一遍又一遍
        4. (如果分配不要求)使用迭代解决方案,而不是递归解决方案

        仅使用 #1-3,您最终会得到:

        def fibo(n):   # Using plain function, defined once outside loop
            if n < 2:
                return n
            return fib(n - 1) + fibo(n - 2)
        
        while True:
            n = input()
            if n.lower() == 'end':
                break
            print(fibo(int(n)))  # Convert to int only once
        

        如果您不需要使用递归解决方案,请不要;斐波那契生成实际上是递归的一个非常糟糕的用途,因此将函数重新定义为:

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

        执行O(n) 工作而不是O(2**n) 工作。记忆可以加快递归解决方案的速度(通过用@functools.lru_cache(maxsize=None) 装饰fibo),但是当迭代解决方案快得多并且首先不需要缓存时,这几乎不值得麻烦。

        【讨论】:

          猜你喜欢
          • 2018-05-29
          • 2016-08-12
          • 2015-10-14
          • 2011-10-26
          • 2018-07-10
          • 2010-12-05
          • 1970-01-01
          • 2017-02-13
          • 2015-02-02
          相关资源
          最近更新 更多