贴一下动态规划的步骤(5步),就像是之前递归一样,需要每次落实到位。
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 举例推导dp数组
509. 斐波那契
注意到n的范围是30以内,一个更快的方法是直接把这个数组先算出来,然后直接取。
class Solution(object):
def fib(self, n):
"""
:type n: int
:rtype: int
"""
fib_list = self.pre_print()
return fib_list[n]
def pre_print(self):
fib_list = [0, 1, 1]
for i in range(3, 31):
fib_list.append(fib_list[i-2] + fib_list[i-1])
return fib_list
当然可以使用递归:
class Solution(object):
def fib(self, n):
"""
:type n: int
:rtype: int
"""
## 递归解法
if n < 2:
return n
else:
return self.fib(n-1) + self.fib(n-2)
70. 爬楼梯
在规定了每次只能走1或者2步的时候,本题的本质就是求解斐波那契鹅数列。
可以看到,dp[i]在第三位开始,往前看一位dp[i-1],只有一种情况(就是走1步),往前看两位dp[i-2],只有一种情况(就是走2步,因为走1步的已经算在dp[i-1]里面了)
所以dp[i]=dp[i-1]+dp[i-2]
则自然可以看出是斐波那契。
关于dp[0]的初始化:由于题目说是从1开始,所以0直接排除了。但是对于一般的动态规划为题(如之前的斐波那契),都需要考虑0的初始化。本题直接初始化dp[1]=1,dp[2]=2即可。
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n <= 2:
return n
# 初始化
dp = [0] * 3
dp[1] = 1
dp[2] = 2 # 实际上只用到了2个位置
# 推倒关系
for i in range(3, n+1): # 注意i开始和结束的值
total = dp[1] + dp[2]
dp[1] = dp[2]
dp[2] = total
return dp[2]
746. 使用最小花费爬楼梯
本题关键在于如何确定dp数组和下标的含义。
1、确定dp数组和下标的含义:数组的第i个代表走到第i个所需要的最小花费;
2、初始化:由于0和1不需要花费,所以dp都是0;
3、递推:当前i个的最小花费是取决于前2个dp值和cost的值,取和的最小值。
class Solution(object):
def minCostClimbingStairs(self, cost):
"""
:type cost: List[int]
:rtype: int
"""
dp = [0] * (len(cost)+1)
dp[0], dp[1] = 0, 0
for i in range(2, len(dp)):
dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
return dp[-1]
Day38完结!!!