代码随想录算法训练营第三十九天 | 322. 零钱兑换、279.完全平方数、139.单词拆分、多重背包理论基础、背包问题总结

一、322. 零钱兑换

题目链接:322. 零钱兑换 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——322. 零钱兑换
视频讲解:动态规划之完全背包,装满背包最少的物品件数是多少?| LeetCode:322.零钱兑换_哔哩哔哩_bilibili

动态规划五部曲:

1. 确定 dp 数组及下标含义:装满容量为 j 的背包最少 dp[ j ]件物品,最后结果 dp[ amount ]
2. 确定递推公式:dp[ j ] = min( dp[ j - coins[ i ]] + 1, dp[ j ]),dp[ j - coins[ i ]] 表示装满 j - coins[ i ] 最的数量,再加上 coins[ i ] 的价值 1
3. 确定dp数组如何初始化:dp[ 0 ] = 0,因为递推为取最小值,所以非零下边初始化为最大值 inf
4. 确定遍历顺序:先遍历物品或先遍历背包均可。
# 先遍历物品
for coin in coins:
        # 再遍历背包
        for j in range(coins[ i ], amount + 1):
                递推公式
5. 举例推导dp数组。

class Solution:
    def coinChange(self, coins: List[int], amount: int) -> int:
        # 创建dp数组
        dp = [float("inf")] * (amount + 1)

        # 初始化
        dp[0] = 0

        # 先遍历物品,即硬币
        for coin in coins:
            # 再遍历背包
            for j in range(coin, amount + 1):
                dp[j] = min(dp[j - coin] + 1, dp[j])

        # 如果仍为初始值,即表示无法组合,返回 -1
        if dp[amount] == float("inf"):
            return -1

        return dp[amount]

二、279.完全平方数

题目链接:279. 完全平方数 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——279.完全平方数
视频讲解:动态规划之完全背包,换汤不换药!| LeetCode:279.完全平方数_哔哩哔哩_bilibili

思路:题意也就是给你一个容量为 n 的背包,有一堆价值为 1, 4, 9,16…的物品,问装满这个背包最少需要多少个物品?和上一题零钱兑换一样。

动态规划五部曲:

1. 确定 dp 数组及下标含义:装满容量为 j 的背包最少 dp[ j ]件物品,最后结果 dp[ n ]
2. 确定递推公式:dp[ j ] = min(dp[ j - i ** 2 ] + 1, dp[ j ])
3. 确定dp数组如何初始化:dp[ 0 ] = 0,因为递推为取最小值,所以非零下边初始化为最大值 inf
4. 确定遍历顺序:先遍历物品或先遍历背包均可。
# 先遍历物品
for i in range(1, int(n ** 0.5) + 1):
        # 再遍历背包
        for j in range(i * i, n + 1):
                递推公式
5. 举例推导dp数组。

class Solution:
    def numSquares(self, n: int) -> int:
        # 创建dp数组
        dp = [float("inf")] * (n + 1)

        # 初始化
        dp[0] = 0

        # 先遍历物品
        for i in range(1, int(n ** 0.5) + 1):
            # 后遍历背包
            for j in range(i * i, n + 1):
                dp[j] = min(dp[j - i ** 2] + 1, dp[j])

        return dp[n]

三、139.单词拆分

题目链接:139. 单词拆分 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——139.单词拆分
视频讲解:动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili

思路:字符串看作背包,单词为物品,问物品能否装满背包。

动态规划五部曲:

1. 确定 dp 数组及下标含义:长度为 i 的字符串,能被单词组成,dp[ i ] = True,输出 dp[ len(s) ]
2. 确定递推公式:if s[ j : i ] and dp[ j ] == True: dp[ i ] = True
3. 确定dp数组如何初始化:dp[ 0 ] = True,非 0 下标都初始化为 False
4. 确定遍历顺序:装满背包对物品顺序有要求,因此需要先遍历背包,再遍历物品
# 先遍历背包
for i in range(1, len(s)  + 1):
        # 再遍历物品
        for j in range(i):
                递推公式
5. 举例推导dp数组。

class Solution:
    def wordBreak(self, s: str, wordDict: List[str]) -> bool:
        # 创建全为 False 的 dp 数组
        dp = [False] * (len(s) + 1)

        # 初始化
        dp[0] = True

        # 先遍历背包
        for i in range(1, len(s) + 1):
            # 再遍历物品,即单词
            for j in range(i):
                if s[j:i] in wordDict and dp[j] == True:
                    dp[i] = True
                    break

        return dp[len(s)]

四、多重背包理论基础

题目链接:56. 携带矿石资源(第八期模拟笔试) (kamacoder.com)
文章讲解:代码随想录 (programmercarl.com)——多重背包理论基础

将物品数量展开就变成了0-1背包问题。

五、背包问题总结

递推公式

问能否能装满背包(或者最多装多少):dp[ j ] = max(dp[ j ], dp[ j - nums[ i ]] + nums[ i ]),对应题目:

问装满背包有几种方法:dp[ j ] += dp[ j - nums[ i ]],对应题目:

问背包装满最大价值:dp[ j ] = max(dp[ j ], dp[ j - weight[ i ]] + value[ i ]),对应题目:

问装满背包所有物品的最小个数:dp[ j ] = min(dp[ j - coins[ i ]] + 1, dp[ j ]),对应题目:

遍历顺序

0-1背包

二维0-1 dp数组背包问题中,先遍历物品还是先遍历背包均可,且第二层循环从小到大正序遍历;
一维0-1 dp数组背包问题中,必须先遍历物品,再遍历背包,且背包从大到小倒序遍历。

完全背包

纯完全背包问题,先遍历物品还是先遍历背包均可,且第二层循环从小到大正序遍历;
如果为排列问题,即强调顺序,必须先遍历背包,再遍历物品;
如果为组合问题,即不强调顺序,必须先遍历物品,再遍历背包。

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值