动态规划是一种可以用作对普通递归进行优化的方法。无论我们在哪里看到重复调用相同输入的递归解决方案,我们都可以使用动态规划对其进行优化。这个想法是简单地存储子问题的结果,这样我们就不必在以后需要时重新计算它们。这种简单的优化将时间复杂度从指数降低到多项式。本文讨论了一种使用Python字典实现动态规划的方法。
为了理解动态规划在Python,让我们使用斐波那契数列问题对其进行可视化。
在数学术语中,斐波那契数列由递推关系定义:
Fn = Fn-1 + Fn-2
种子值:
F0 = 0 and F1 = 1
例子:
Input: N = 9
Output: 34
Explanation:
9th number in the Fibonacci series is 34.
Input: N = 2
Output: 1
Explanation:
2nd number in the Fibonacci series is 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 现场工作专业课程和学生竞争性编程现场课程。