代码随想录算法训练营第二十八天| 理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

动态规划五部曲

1、确定dp数组(dp table)以及下标的含义
2、确定递推公式
3、dp数组如何初始化
4、确定遍历顺序
5、举例推导dp数组

509. 斐波那契数

思路

动态规划五部曲解决。
解决问题1:dp[i]的的含义是什么?是斐波那契数组的第i位的数值。
解决问题2:递推公式是什么?递推公式根据斐波那契数列可以知道,后一位数字是由前面两位数字组成的,所以递推公式是dp[i]=dp[i-1]+dp[i-2]。
解决问题3:dp数组如何初始化?根据斐波那契数列可以知道,如果想要第i位的数字就需要前面两位的数字,所以最开始的两位数字要是已知的,这样才能计算后面的数字。
解决问题4:如何确定遍历顺序?根据斐波那契数列知道,初始的两位数字是要初始化知道的,所以要从左到右进行遍历。
解决问题5:输出搭配数组。为了判断是否和题意一致,方便后续改错。
错误第一版:当n为0的时候没判断。

class Solution:
    def fib(self, n: int) -> int:
        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-1]

正确代码

class Solution:
    def fib(self, n: int) -> int:
        if n == 0:
            return 0
        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-1]

70. 爬楼梯

思路

乍一看感觉好复杂,总不能一种一种查吧。。。。
动态规划五部曲解决。
解决问题1:dp[i]的的含义是什么?到达第i阶有dp[i]种方法。
解决问题2:递推公式是什么?我们从第一阶开始看,如果是1阶台阶,那么只有一种方法到达,就是走一步,所以只有1种方法;如果是2阶台阶,那么有两种方法,一个是1+1,一个是2,这两种方法都能到达第2阶,所以一共2种方法;如果是3阶台阶,那么要么是从第一阶迈两步上来,要么是从第二阶迈一步上来,从第一阶迈的话,那么走到第一阶只有一种方法,如果从第二阶迈的话,那么走到第二阶有两种方法,这都是根据前面的说明得到的结论,所以一共有1+2=3种办法上到3阶;同理走到4阶也是只有两种情况,要么是从第三阶走一步,要么是从第二阶走两步,结果也是3+2=5,所以递推公式是dp[i]=dp[i-1]+dp[i-2]。
解决问题3:dp数组如何初始化?根据上面的解决问题2可以知道,如果想要第i位的数字就需要前面两位的数字,所以最开始的两位数字要是已知的,这样才能计算后面的数字。
解决问题4:如何确定遍历顺序?根据斐波那契数列知道,初始的两位数字是要初始化知道的,所以要从左到右进行遍历。
解决问题5:输出搭配数组。为了判断是否和题意一致,方便后续改错。
注意:不要纠结去考虑0的情况!!!!
错误第一版:报错为数组出界,我们只判断了从两阶台阶开始的情况,两阶台阶对应的是n=2的时候,所以应该前面应该加一个判断条件,当n<2的时候的情况,小于2阶台阶的时候就是一阶或者没有那么就输出自身即可。

class Solution:
    def climbStairs(self, n: int) -> int:
        dp = [0] * (n+1)
        dp[1] = 1
        dp[2] = 2
        for i in range(3,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]

正确代码

class Solution:
    def climbStairs(self, n: int) -> int:
        if n < 2:
            return n
        dp = [0] * (n+1)
        dp[1] = 1
        dp[2] = 2
        for i in range(3,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]

746. 使用最小花费爬楼梯

思路

解析一下题意,不仅仅是爬楼梯,还有初始位置是可以选择的,要么是0要么是1,并且每个位置都是有花销的,本题是想要最小的花销爬到最顶上。
解决问题1:dp[i]的的含义是什么?是爬到第i个台阶的最小花销。
解决问题2:递推公式是什么?递推公式根据第i个台阶的花销是由前面第i-1位的最小花销加上第i-1位的花销或者第i-2位的最小花销加上第i-2位的花销,所以递推公式是dp[i]=min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])。
解决问题3:dp数组如何初始化?我们看递推公式可以看出,第i位需要第i-1位和第i-2位的dp值,也就是说第2位需要第1位和第0位的值,所以初始化的是dp[0],dp[1]。但是初始化的值需要注意一下,我们设置的是dp数组为走到第i个台阶的最小值,也就是最后直接输出的数组中的值,只有走了这一步才加上这一步的cost值,所以当cost长度为0的时候证明一步都不走,dp[0]=0,当cost长度为1的时候,按照题中要求可以从0或者1进行初始化,那么也就是说从1开始走也可以,所以当dp[1]的时候也可以是开始要走的位置,但是数组长度为1,他还没继续向下走,没走就不能+cost的值,所以初始化为0。
解决问题4:如何确定遍历顺序?根据递推公式知道,初始的两位数字是要初始化知道的,所以要从左到右进行遍历。
解决问题5:输出搭配数组。为了判断是否和题意一致,方便后续改错。
正确代码

class Solution:
    def minCostClimbingStairs(self, cost: List[int]) -> int:
        dp = [0] * (len(cost) + 1)
        dp[0] = 0
        dp[1] = 0
        for i in range(2,len(cost)+1):
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])
        return dp[len(cost)]
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值