今天从懂太规划的入门篇开始
分别是Leetcode509/70/746
Leetcode509
509. 斐波那契数 - 力扣(Leetcode)
这道题 按照我们之前递归的思路来说 我们已经知道这道题的递推公式 f(n) = f(n-1)+f(n-2)。
确定动态规划五部曲:
1.确定dp数组以及下标的含义
dp[i]的定义为:第i个数的斐波那契数值是dp[i]
2.确定递推公式
dp[i] = dp[i-1]+dp[i-2]
3.数组如何初始话
dp[0] = 0
dp[1] = [1]
4.确定遍历顺序
从递归公式dp[i] = dp[i - 1] + dp[i - 2]中可以看出,
dp[i]是依赖 dp[i - 1] 和 dp[i - 2],
那么遍历的顺序一定是从前到后遍历的
5.举例推导dp数组
按照这个递推公式dp[i] = dp[i - 1] + dp[i - 2],
我们来推导一下,当N为10的时候,dp数组应该是如下的数列:
0 1 1 2 3 5 8 13 21 34 55
如果代码写出来,发现结果不对,
就把dp数组打印出来看看和我们推导的数列是不是一致的。
这里我就用python的写法
a,b,c来代替dp数组 然后相互交换
def fib(self, n: int) -> int:
if n<2:
return n
a = 0
b = 1
c = 0
for i in range(1,n):
c = a+b
a,b = b,c
return c
这里c的作用是用来保存前两个相加的和
a代表dp[0],b代表dp[1]
Leetcode70爬楼梯
力扣
这道题 经过我 多次画图验证的出
爬1个阶梯 有1种方法
爬2个阶梯 有2种方法
爬3个阶梯 有3种方法
爬4个阶梯 有5种方法
从这个例子可以看出来 爬第n层楼的阶梯有几种方法是由前两个方法相加 也就是第n-1个阶梯的方法+n-2个阶梯的方法相加得出
注意!!!!这里是找方法而不是找爬到第几阶梯需要的步数
其次就是 我们既然已经知道了递推公式
那么有一个问题在这里了,如果i = 0 ,也就是当我们在第0层的时候,我们的dp[0]应该初始化为多少呢,是0还是1呢?
这个可以有很多解释,但都基本是直接奔着答案去解释的。
例如强行安慰自己爬到第0层,也有一种方法,什么都不做也就是一种方法即:dp[0] = 1,相当于直接站在楼顶。
但总有点牵强的成分。
那还这么理解呢:我就认为跑到第0层,方法就是0啊,一步只能走一个台阶或者两个台阶,然而楼层是0,直接站楼顶上了,就是不用方法,dp[0]就应该是0.
其实这么争论下去没有意义,大部分解释说dp[0]应该为1的理由其实是因为dp[0]=1的话在递推的过程中i从2开始遍历本题就能过,然后就往结果上靠去解释dp[0] = 1。
从dp数组定义的角度上来说,dp[0] = 0 也能说得通。
需要注意的是:题目中说了n是一个正整数,题目根本就没说n有为0的情况。
所以本题其实就不应该讨论dp[0]的初始化!
我相信dp[1] = 1,dp[2] = 2,这个初始化大家应该都没有争议的。
所以我的原则是:不考虑dp[0]如果初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。
代码:
def climbStairs(self, n: int) -> int:
#递归实现
# if n==0 or n==1:
# return 1
# return self.climbStairs(n-1) + self.climbStairs(n-2)
"""动态规划实现"""
#当n = 0 or 1 的时候都返回是1
dp = [0] * (n+1)
dp[0] = 1
dp[1] = 1
for i in range(2,n+1):
dp[i] = dp[i-1] + dp[i-2]
return dp[n]
Leetcode746使用最小花费爬楼梯
力扣
EMMMMM,这道题出的很好。。下次建议换个出题人
运用动态规划来解决这道题,说实话到现在我都是懵逼的,读不懂题意,爬个楼梯还要给钱??
这里代码先放了
欢迎各位大佬来指点一下
def minCostClimbingStairs(self, cost: List[int]) -> int:
dp = [0] * (len(cost))
dp[0] = cost[0]
dp[1] = cost[1]
for i in range(2, len(cost)):
dp[i] = min(dp[i - 1], dp[i - 2]) + cost[i]
return min(dp[len(cost) - 1], dp[len(cost) - 2])