核心思想:
将问题分解为重叠的子问题,并储存子问题的解(使用字典、数组或哈希表),避免重复计算,从而提高效率。
题目特点:重叠子问题(特殊地,是最优子结构)
比如:斐波那契数列问题中,递归求F(5),需要多次计算F(3);
最短路径问题中,若从A到C的最优路径包含B,则A到B和B到C也必然是最优的。
两种实现方式:
自顶向下(递归+储存记忆,将大问题逐步分解,子问题的解储存在字典里):
class Solution(object):
# 把momory作为类属性
memory = {}
def fib(self, n):
# 如果已经在记忆里储存,则直接返回,不用再重复计算
if n in self.memory:
return self.memory[n]
if n<=1:
return n
self.memory[n] = self.fib(n-1)+self.fib(n-2)
return self.memory[n]
自底向上(迭代+储存记忆,先解决小问题再解决大问题,小问题的解储存在数组里):
class Solution(object):
def fib(self, n):
"""
:type n: int
:rtype: int
"""
dp = [0,1] # 动态规划数组,初始值相当于递归里遇到终止条件能直接返回的值
for i in range(2,n+1):
dp.append(dp[i-1]+dp[i-2])
return dp[n]
解题步骤:
1、定义状态(dp[i]表示什么)
2、写状态转移方程(由局部最优一直推到全局最优,所以从初始截断到当前位置来考虑即可,后面的先不管)
3、确定初始状态(起码两个)
3、用递归or迭代解题
比如:“打家劫舍”求数组中不相邻元素组合,使值的和最大
(1)定义状态:设dp[i]表示从第0到第i个中元素组合的最优解