518.零钱兑换II
代码随想录:
可重复,离散值,凑成背包容量,最后求取的有多少种方法,是完全背包类的应用。
- dp[j]:装满容量为j的背包有dp[j]种方法
- 递推公式
这个递推公式大家应该不陌生了,我在讲解01背包题目的时候在这篇494. 目标和 (opens new window)中就讲解了,求装满背包有几种方法,公式都是:dp[j] += dp[j - nums[i]];
- 初始化:
- dp [ j ] = 1;装满容量为0的背包有1种方法
- 遍历顺序:
- 先正序遍历物品
- 再正序遍历背包容量 ,j = weight [i] ;j<=amount;j++
- 先正序遍历物品
代码
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount+1];
dp[0] = 1;
for (int i = 0; i < coins.length; i++) {
for (int j = coins[i]; j <= amount; j++) {
dp[j] += dp[j-coins[i]];
}
}
return dp[amount];
}
}
377.组合总和IV
第一想法
完全背包问题,并且求出方法数,区别在于:顺序不同的序列被视作不同的组合。
代码随想录
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
如果把遍历nums(物品)放在外循环,遍历target的作为内循环的话,举一个例子:计算dp[4]的时候,结果集只有 {1,3} 这样的集合,不会有{3,1}这样的集合,因为nums遍历放在外层,3只能出现在1后面!
所以本题遍历顺序最终遍历顺序:target(背包)放在外循环,将nums(物品)放在内循环,内循环从前到后遍历。
代码
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target+1];
dp[0] = 1;
for (int j = 0; j <= target; j++) {
for (int i = 0; i < nums.length; i++) {
if (j >= nums[i]) {
dp[j] += dp[j - nums[i]];
}
}
}
return dp[target];
}
}
70.爬楼梯
这道题目 爬楼梯之前我们做过,这次再用完全背包的思路来分析一遍
完全背包问题,可以爬1阶,2阶。。。。m阶,其实就是可以m个物品,而爬到楼顶其实就时是背包容量为n.
遍历顺序:先遍历背包,再遍历物品。因为从题意上看1 2 1和 1 1 2 显然是两种不同方法,此题是一个排列问题。