反正基本思路就是遍历硬币,然后依次遍历数量。
零钱兑换:https://leetcode.cn/problems/coin-change/
零钱兑换 II:https://leetcode.cn/problems/coin-change-ii/
关于零钱2的变种类题目:
零钱2是组合,顺序不重要 这个是排列:(顺序比较重要)
相似的题是:LeetCode 377. 组合总和 Ⅳ (Combination Sum IV)https://leetcode.cn/problems/combination-sum-iv/description/ (挂羊头卖狗肉,名为组合实为排列)
假设你正在爬一个 n 阶的楼梯。你每次可以向上爬 1 阶、2 阶 或者 4 阶。请问,爬到楼顶(第 n 阶)一共有多少种不同的方法?(注意:不同的攀爬顺序被视为不同的方法。例如,1+2 和 2+1 是两种不同的方法。)
关于完全背包类问题的两种遍历方式。顺序重要是排序,外背包内物品。 顺序不重要的是组合,外物品内背包。
- 如果是01背包,一般是外物品后背包。
js
function solveCounting(target, nums) {
const dp = new Array(target + 1).fill(0);
dp[0] = 1;
// 决策点:这是排列还是组合?
// CASE A: 爬楼梯 / 组合总和 IV (顺序重要 -> 排列)
// 逻辑:背包在外,物品在内
/*
for (let i = 1; i <= target; i++) { // 遍历背包
for (let num of nums) { // 遍历物品
if (i >= num) dp[i] += dp[i - num];
}
}
*/
// CASE B: 零钱兑换 II (顺序不重要 -> 组合)
// 逻辑:物品在外,背包在内
/*
for (let num of nums) { // 遍历物品
for (let i = num; i <= target; i++) { // 遍历背包
dp[i] += dp[i - num];
}
}
*/
return dp[target];
}综上:
下次拿到这种题,按这个流程思考:
- 是背包问题吗?(能从一堆数里凑出一个总和) -> Yes.
- 物品能重复用吗?
- 不能 -> 0/1 背包 -> 内层循环倒着写。
- 能 -> 完全背包 -> 内层循环正着写。
- 求的是什么?
- 求最值 (Min/Max) -> 循环顺序无所谓 (习惯先物品)。
- 求方案数 (Count) -> 看顺序!
- 顺序无关 (组合) -> 先物品 (零钱II)。
- 顺序有关 (排列) -> 先背包 (组合IV, 爬楼梯)。