动态规划——dp的含义归类(完全背包和01背包区别)
1.代码随想录-逆波兰式、滑动窗口最大值2.代码随想录-栈与队列-有效的括号(括号匹配)3.代码随想录——栈与队列8-前K个高频元素4.二叉树的递归遍历和迭代遍历5.代码随想录——二叉树-11.完全二叉树的节点个数6.代码随想录——二叉树-12.平衡二叉树7.代码随想录——二叉树17-路径总和8.代码随想录——二叉树19.最大二叉树9.代码随想录——二叉树21、合并二叉树(附:递归算法复杂度分析)10.代码随想录——二叉树23、验证二叉搜索树11.代码随想录——25二叉搜索树的最小绝对值差(递归遍历如何记录前后两个指针)12.代码随想录——25.二叉搜索树中的众数13.代码随想录——26、二叉(搜索)树的最近公共祖先14.代码随想录——回溯8、组合总和II15.代码随想录——回溯9.分割回文串16.代码随想录——回溯19重新安排行程17.代码随想录——回溯 N皇后18.代码随想录——贪心8.跳跃游戏II19.代码随想录——贪心9.K次取反后最大化的数组和 && std::sort函数的第三个参数说明20.代码随想录——贪心13.分发糖果21.代码随想录——贪心算法:根据身高重建队列 & Vector原理22.代码随想录——贪心算法22单调递增的数字23.代码随想录——贪心23监控二叉树24.代码随想录——动态规划5.周总结25.代码随想录——动态规划9不同的二叉搜索树26.代码随想录——动态规划01背包27.代码随想录——动态规划13.分割等和子集28.代码随想录——动态规划14最后一块石头的重量II(01背包)
29.动态规划——dp的含义归类(完全背包和01背包区别)
30.动态规划——26单词拆分31.代码随想录——动态规划背包问题总结32.代码随想录——动态规划31打家劫舍III(树状DP)33.代码随想录——动态规划、股票问题34.代码随想录——单调栈35.回溯总结- 用dp表示总价值
- 用dp表示组合数
给出一个总数,一些物品,问能否凑成这个总数。
零钱兑换II https://leetcode.cn/problems/coin-change-ii/
完全背包
二维写法
for (int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = 0; j <= bagWeight; j++) { // 遍历背包容量
if (j < weight[i]) dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j], dp[i][j - weight[i]] + value[i]);
}
}
一维写法
// 先遍历物品,再遍历背包
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = weight[i]; j < bagWeight ; j++) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
为什么要先遍历物品,在遍历背包呢? (灵魂拷问)
其实纯完全背包,先遍历物品,再遍历背包 与 先遍历背包,再遍历物品都是可以的。
零钱兑换II 不是纯完全背包(求是否能装满背包),而是求装满背包有几种方法。
这里在遍历顺序上可就有说法了。
- 如果求组合数就是外层for循环遍历物品,内层for遍历背包。
- 如果求排列数就是外层for遍历背包,内层for循环遍历物品。
为什么会有这种区别?
组合数 是不考虑顺序的,即只关心哪些硬币被选中了,不关心它们的顺序。第一个代码块中,每个硬币依次处理,确保了每个硬币只会按照固定顺序被考虑,因此不会重复计算顺序不同但硬币相同的组合。
排列数 是考虑顺序的,即不同顺序的硬币视为不同的方案。第二个代码块中,每次更新金额时,都考虑了所有硬币的排列,因此会计算所有可能的排列。
for (int j = 0; j <= amount; j++) { // 遍历背包容量
for (int i = 0; i < coins.size(); i++) { // 遍历物品
if (j - coins[i] >= 0) dp[j] += dp[j - coins[i]];
}
}
每次更新容量时,遍历一遍所有物品作为当前可能要选择的物品
一维
遍历的时候和01背包不同,01背包需要内层(容量)倒序遍历。而完全背包不需要。这是因为完全背包的递推公式不一样:
如求组合数的递推公式:
完全背包:
二维递推公式:dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]]
压缩成一维:dp[j] += dp[j - coins[i]]
01背包:
二维递推公式:dp[i][j] = dp[i - 1][j] + dp[i-1][j - coins[i]]
压缩成一维:dp[j] += dp[j - coins[i]]
区别: 01背包需要内层倒序遍历,防止覆盖前一层的值;完全背包不需要倒序遍历。
总结
求组合数:518.零钱兑换II
求排列数:377. 组合总和 Ⅳ 70. 爬楼梯进阶版(完全背包)
求最小数:322. 零钱兑换 、279.完全平方数
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现