算法相关数据结构总结:
| 序号 | 数据结构 | 文章 |
|---|---|---|
| 1 | 动态规划 | 动态规划之背包问题——01背包 动态规划之背包问题——完全背包 动态规划之打家劫舍系列问题 动态规划之股票买卖系列问题 动态规划之子序列问题 算法(Java)——动态规划 |
| 2 | 数组 | 算法分析之数组问题 |
| 3 | 链表 | 算法分析之链表问题 算法(Java)——链表 |
| 4 | 二叉树 | 算法分析之二叉树 算法分析之二叉树遍历 算法分析之二叉树常见问题 算法(Java)——二叉树 |
| 5 | 哈希表 | 算法分析之哈希表 算法(Java)——HashMap、HashSet、ArrayList |
| 6 | 字符串 | 算法分析之字符串 算法(Java)——字符串String |
| 7 | 栈和队列 | 算法分析之栈和队列 算法(Java)——栈、队列、堆 |
| 8 | 贪心算法 | 算法分析之贪心算法 |
| 9 | 回溯 | Java实现回溯算法入门(排列+组合+子集) Java实现回溯算法进阶(搜索) |
| 10 | 二分查找 | 算法(Java)——二分法查找 |
| 11 | 双指针、滑动窗口 | 算法(Java)——双指针 算法分析之滑动窗口类问题 |
文章目录
前面整理了01背包,在leetcode题库中主要就是01背包和完全背包问题,所以在这里整理一下完全背包的知识点。
一、完全背包问题
有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。
完全背包和01背包问题唯一不同的地方就是,每种物品有无限件。
注:leetcode上没有纯完全背包问题,都是需要完全背包的各种应用,需要转化成完全背包问题。
01背包和完全背包唯一不同就是体现在遍历顺序上,所以针对遍历顺序进行分析。其它动规五部曲参考01背包。
二、完全背包遍历顺序
首先回顾一下01背包的遍历顺序:
for(int i = 0; i < weight.size(); i++) {
// 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) {
// 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
我们知道01背包内嵌的循环是从大到小遍历,为了保证每个物品仅被添加一次。
而完全背包的物品是可以添加多次的,所以要从小到大去遍历,即:
// 先遍历物品,再遍历背包
int[] dp = new int[bagWeight + 1];
for (int i = 0; i < weight.length; i++){
for (int j = 1; j <= bagWeight; j++){
if (j - weight[i] >= 0){
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
}
为什么遍历物品在外层循环,遍历背包容量在内层循环?
在01背包中二维dp数组的两个for遍历的先后循序是可以颠倒,一维dp数组的两个for循环先后循序一定是先遍历物品,再遍历背包容量。
在完全背包中,对于一维dp数组来说,其实两个for循环嵌套顺序同样无所谓。
因为dp[j] 是根据 下标j之前所对应的dp[j]计算出来的。 只要保证下标j之前的dp[j]都是经过计算的就可以。完全背包中,两个for循环的先后循序,都不影响计算dp[j]所需要的值。
先遍历被背包在遍历物品,代码如下:
// 先遍历背包,再遍历物品
for(int j = 0; j <= bagWeight; j++) {
// 遍历背包容量
for(int i = 0; i < weight.size(); i++) {
// 遍历物品
if (j - weight[i] >= 0) dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
}
注:全文说的都是对于纯完全背包问题,其for循环的先后循环是可以颠倒的!但如果题目稍稍有点变化,就会体现在遍历顺序上。
如果问装满背包有几种方式的话? 那么两个for循环的先后顺序就有很大区别了,而leetcode上的题目都是这种稍有变化的类型。这些将根据具体的题目进行分析。
三、leetcode例题讲解完全背包问题
518. 零钱兑换 II
leetcode题目链接:518. 零钱兑换 II
给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。
请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
假设每一种面额的硬币有无限个。
示例一:
输入:amount = 5, coins = [1, 2, 5]
输出:4
解释:有四种方式可以凑成总金额:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
示例二:
输入:amount = 3, coins = [2]
输出:0
解释:只用面额 2 的硬币不能凑成总金额 3 。
示例三:
输入:amount = 10, coins = [10]
输出:1
这是一道典型的背包
完全背包问题详解与LeetCode实战

这篇博客详细介绍了完全背包问题,与01背包的区别在于每种物品可无限件。文章通过分析完全背包的遍历顺序,讲解了完全背包在LeetCode上的应用,如求解组合总和、零钱兑换等问题。博主还分享了如何确定动态规划的五个步骤,以及针对不同题目调整遍历顺序的关键。最后,总结了完全背包问题的递推公式和遍历顺序策略。
最低0.47元/天 解锁文章
908





