动态规划07 | ● 70. 爬楼梯 (进阶) ● 322. 零钱兑换 ● 279.完全平方数

70. 爬楼梯 (进阶)

https://programmercarl.com/0070.%E7%88%AC%E6%A5%BC%E6%A2%AF%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85%E7%89%88%E6%9C%AC.html

  • 考点
    • 完全背包
  • 我的思路
    • 本题就是用完全背包的思路解决排列问题,一个背包、多个物品(无限拿取)求装满背包有多少种排列
  • 视频讲解关键点总结
    • 无视频
  • 我的思路的问题
  • 代码书写问题
  • 可执行代码
class Solution:
    def climbStairs(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[0] = 1
        for j in range(1, n + 1):
            for i in range(1, 3):
                if j >= i:
                    dp[j] += dp[j - i]
        return dp[-1]

322. 零钱兑换

视频讲解:https://www.bilibili.com/video/BV14K411R7yv
https://programmercarl.com/0322.%E9%9B%B6%E9%92%B1%E5%85%91%E6%8D%A2.html

  • 考点
    • 动态规划
    • 完全背包
  • 我的思路
    • 给定一个背包容量和多个物品,求装满背包使用的最少物品个数,如果物品无法装满背包,返回-1
    • dp[j] 的含义是当容量为 j 时,装满背包所用的物品的最少个数
    • 递推公式,dp[j] = min(dp[j], dp[j - coins[i]] + 1),求取当前物品和不取当前物品对应的最小值为dp值
    • 关键点1,初始化,这是一个本题的关键
      • 首先当j 为 0时,初始化dp为0,这点没有问题
      • 对于剩下的dp数组(非零下标),应该怎么初始化?这就要基于递推公式来分析了,递推公式中对于后续每个值,都是基于最小化的思想来迭代的,如果dp数组全初始化为0,则后续递推过程由于取最小值,整个dp数组将保持为0;所以,应该在初始化时,把后面的dp值初始化为一个极大值,这样才能保证递推过程正常进行
    • 遍历顺序——内外双循环(可以相互颠倒,因为本题既不是组合问题也不是排列问题,求最小数量和取物品的顺序无关),内外层循环均正向遍历(因为是完全背包问题,每个物品可以取多次)
    • 关键点2,对于物品无法装满背包的判断
      • 什么情况下物品装不满背包?其实就是无论怎么组合,背包最后所剩的容量小于重量最小的物品,这种情况下背包无法装满
      • 由于在递推公式中,如果背包容量小于物品重量,该dp值将保持初始化时的极大值,因此,如果dp递推结束后,对应的dp[-1]的值为初始化的极大值,则代表背包无法装满,此时返回-1
  • 视频讲解关键点总结
    • 本题求最小数量既不是组合问题也不是排列问题,其与取物品的顺序无关
  • 我的思路的问题
    • 对于内外层循环是否能颠倒一开始没想明白,以为本题是组合问题,其实本题无关顺序
  • 代码书写问题
    • 可以利用float('inf')来取极大值
  • 可执行代码
class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        dp = [float('inf')] * (amount + 1)
        dp[0] = 0
        for i in range(len(coins)):
            for j in range(1, amount + 1):
                if j >= coins[i]:
                    dp[j] = min(dp[j], dp[j - coins[i]] + 1)
        if dp[-1] == float('inf'):
            return -1
        return dp[-1]

279.完全平方数

  • 考点
    • 动态规划
    • 完全背包
  • 我的思路
    • 先找到所有比目标值小的完全平方数(可以通过int(sqrt(i)) == sqrt(i)来判断)
    • 之后背包容量是目标值,物品是完全平方数集合,无限次拿取,看装满背包的最小物品数是多少
  • 视频讲解关键点总结
    • 关键点1,不需要寻找完全平方数,从1开始遍历数字 i ,之后递推公式里用 i ** 2 代替 i 即为使用完全平方数了
    • 关键点2,遍历背包容量时从i ** 2开始遍历即可,因为小于该数值,当前物品一定无法被放入背包,所以dp值不变,不需要进行额外操作
  • 我的思路的问题
    • 遗漏一个关键,本题一定能找到满足题意的组合,因为完全平方数里有1,能组出来任意数字
    • 光想着如何判断一个数字是不是完全平方数了,没想到可以直接通过顺序遍历得到所有的完全平方数
  • 代码书写问题
  • 可执行代码
class Solution:
    def numSquares(self, n: int) -> int:
        dp = [float('inf')] * (n + 1)
        dp[0] = 0
        for num in range(1, int(sqrt(n)) + 1):
            for j in range(num ** 2, n + 1):
                dp[j] = min(dp[j], dp[j - (num ** 2)] + 1)
        return dp[-1]
  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值