📜  Python |使用字典实现动态编程

📅  最后修改于: 2021-04-27 20:22:21             🧑  作者: Mango

动态编程是一种可用于对纯递归进行优化的方法。只要我们看到递归解决方案重复调用相同的输入,就可以使用动态编程对其进行优化。这样做的想法是简单地存储子问题的结果,这样我们就不必在以后需要时重新计算它们。这种简单的优化降低了从指数到多项式的时间复杂度。在本文中,已经讨论了使用Python词典实现动态编程的方法。

为了理解Python动态编程的实现,让我们使用Fibonacci数问题对其进行可视化。

用数学术语来说,斐波纳契数的序列由递归关系定义:

Fn = Fn-1 + Fn-2

具有种子值:

F0 = 0 and F1 = 1

例子:

下面是幼稚方法的实现:

# Function to find nth Fibonacci number 
def Fibonacci(n): 
  
    # Corner case
    if n<0: 
        print("Incorrect input") 
  
    # Base case
    elif n == 0: 
        return 0
    elif n == 1: 
        return 1
  
    # Recursive case
    else: 
        return Fibonacci(n-1)+Fibonacci(n-2)
    
print(Fibonacci(9)) 
输出:
34

显然,上述方法具有指数时间复杂度。为了存储先前计算的结果,让我们使用Python的字典类。

方法:想法是自定义字典类的__missing__方法。当用户尝试访问不在词典中的键时,将执行此方法。我们将使用自己的函数定义来重写此方法。

下面是上述方法的实现:

# Python program to customize the 
# __missing__ method of the 
# dictionary class in python
  
class Fibonacci(dict):
  
    # Function signature of the
    # __missing__ function in 
    # python
    def __missing__(self, n):
          
        # Base case
        if n<= 1:
  
            # Storing the value in the
            # dictionary before returning
            self[n] = n
            return n 
  
        # Storing the value in the dictionary
        # before returning the value
        val = self[n] = self[n-1] + self[n-2]
        return val
  
if __name__ == "__main__":
  
    # Create an instance of the class
    Fib = Fibonacci()
    N = Fib[9]
    print(N)
输出:
34

上述方法也可以通过在Python使用装饰器来实现。

Decorator是Python一个非常强大且有用的工具,因为它允许程序员修改函数或类的行为。装饰器允许我们包装另一个函数,以扩展被包装函数的行为,而无需对其进行永久性修改。在这里,备忘录用于实现装饰器。

下面是上述方法的实现:

# Python program to find the nth Fibonacci
# number with memoization using decorators
  
from inspect import signature
  
# Defining a decorator 
class memoise(dict):
  
    # Initializing function
    def __init__(self, func):
        self.func = func
        self.signature = signature(func)
  
    # Missing method to store the 
    # Fibonacci numbers in a 
    # Dictionary
    def __missing__(self, key):
        (arg, kwarg) = key
        self[key] = val = self.func(*arg,  
                          **dict(kwarg))
        return val
  
    def __call__(self, *arg, **kwarg):
        key = self.signature.bind(*arg, 
                                  **kwarg)
        return self[key.args, 
                    frozenset(key.kwargs.items())]
  
  
# Function to find the n-th Fibonacci 
# number using the above defined 
# decorator
@memoise 
def Fibonacci(n): 
  
    # Corner case
    if n<0: 
        print("Incorrect input") 
  
    # Base cases
    elif n == 0: 
        return 0
    elif n == 1: 
        return 1
  
    # Recursive case
    else: 
        return Fibonacci(n-1)+Fibonacci(n-2)
  
if __name__ == "__main__":
    print(Fibonacci(9)) 
输出:
34