📜  Python|使用字典实现动态规划

📅  最后修改于: 2021-09-04 11:20:14             🧑  作者: Mango

动态规划是一种可以用作对普通递归进行优化的方法。无论我们在哪里看到重复调用相同输入的递归解决方案,我们都可以使用动态规划对其进行优化。这个想法是简单地存储子问题的结果,这样我们就不必在以后需要时重新计算它们。这种简单的优化将时间复杂度从指数降低到多项式。本文讨论了一种使用Python字典实现动态规划的方法。

为了理解动态规划在Python,让我们使用斐波那契数列问题对其进行可视化。

在数学术语中,斐波那契数列由递推关系定义:

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的装饰器来实现。

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

下面是上述方法的实现:

# 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

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live