动规五部曲:
-
dp数组
-
递推公式
-
初始化
-
遍历顺序
-
打印检查
509. 斐波那契数
-
自己写的没什么套路的ac
class Solution:
def fib(self, n: int) -> int:
if n == 0:
return 0
ans = [0]*(n+1)
ans[0] = 0
ans[1] = 1
print(ans)
for i in range(2, n+1):
ans[i] = ans[i-1]+ans[i-2]
print(ans)
return ans[-1]
-
其他的两种解法:
class Solution:
def fib(self, N: int) -> int:
if N<=1:
return N
return self.fib(N-1)+self.fib(N-2)
class Solution:
def fib(self, N):
"""
:type N: int
:rtype: int
"""
a,b=0,1
for x in range(N):
a,b = b,a+b
return a
-
Carl模版解法:实际上第一种写法就是按照动归五部曲来进行的,只是没有意识到
class Solution:
def fib(self, n: int) -> int:
if n == 0:
return 0
#step1: dp数组以及dp[i]的含义:第i个斐波那契数的值
dp = [0]*(n+1)
#step2: 递推公式: dp[i] = dp[i-1]+dp[i-2]
#step3: 初始化
dp[0] = 0
dp[1] = 1
#step4: 遍历顺序
for i in range(2, n+1):
dp[i] = dp[i-1]+dp[i-2]
#step5: 打印检查
return dp[n]
70. 爬楼梯
关键点:(Carl视频讲解留言板)
题目中要求的每次可以爬1或者2个台阶,也就是说,最终到达n阶台阶有两种方式,一个是爬1阶台阶到达(对应的是从n-1阶台阶开始),那么另一个就是爬2阶台阶到达(对应的是从n-2阶台阶开始爬),而爬n-1阶和n-2阶台阶的方法有dp【n-1】,dp【n-2】个。所以最终爬n阶台阶的方法种类就是dp【n-1】+dp【n-2】。其实也对应了卡尔所说的从n-1和n-2阶爬上去,探究的是几种走法,而不是几步。
class Solution:
def climbStairs(self, n: int) -> int:
if n <= 1:
return n
#step1: dp[i]是指到达第i阶有dp[i]种方法
dp = [0]*(n+1)
#step2: 递推公式: dp[i] = dp[i-2] + dp[i-1]
#step3:初始化
'''
为什么不初始化为dp[0]=0, dp[1]=1,这样也能ac?
因为题目限制1<=n<=45,也就是说n不会是0,那么dp[0]含义就没有意义,这样就需要初始化后面两项
'''
dp[1] = 1
dp[2] = 2
#step4: 遍历顺序
for i in range(3, n+1):
dp[i] = dp[i-2] + dp[i-1]
#step5: 打印检查
return dp[n]
remark:
也可以按照题解的方法进行优化,从而空间复杂度为O(1)。但实际原理一样
746. 使用最小花费爬楼梯
五部曲一定要明确
class Solution:
def minCostClimbingStairs(self, cost: List[int]) -> int:
if len(cost) == 1:
return cost[0]
#step1: dp[i]是到达第i个台阶所花费的最少体力为dp[i](包括当前台阶的体力值,对应cost[i])
dp = [0]*len(cost)
#step2: 递推公式: dp[i] = min(dp[i-1], dp[i-2]) + cost[i]
#step3: 初始化
dp[0] = cost[0]
dp[1] = cost[1]
#step4: 遍历顺序
for i in range(2, len(cost)):
dp[i] = min(dp[i-1], dp[i-2]) + cost[i]
#step5: 打印检查
return min(dp[len(cost)-1], dp[len(cost)-2])