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

📅  最后修改于: 2021-09-22 10:21:33             🧑  作者: Mango

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

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

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

Fn = Fn-1 + Fn-2

种子值:

F0 = 0 and F1 = 1

例子:

下面是朴素方法的实现:

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


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


Python3
# Python program to find the nth Fibonacci
# number with memoization using decorators
 
from inspect import signature
 
# Defining a decorator
class memoize(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
@memoize
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

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

做法:思路是自定义字典类的__missing__方法。当用户尝试访问不在字典中的键时执行此方法。我们将使用我们自己的函数定义来重写此方法。
下面是上述方法的实现:

蟒蛇3

# 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 用于实现装饰器。

下面是上述方法的实现:

蟒蛇3

# Python program to find the nth Fibonacci
# number with memoization using decorators
 
from inspect import signature
 
# Defining a decorator
class memoize(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
@memoize
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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程