518. 零钱兑换II
本题是要求凑成总金额的物品组合个数!
五部曲:
- dp[j]:凑成总金额j的货币组合数为dp[j]
- dp[j] 就是所有的dp[j - coins[i]](考虑coins[i]的情况)相加。
- 首先dp[0]一定要为1,dp[0] = 1是 递归公式的基础。
- 外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)的情况。
- 验证
/**
* @param {number} amount
* @param {number[]} coins
* @return {number}
*/
var change = function (amount, coins) {
const dp = new Array(amount + 1).fill(0)
dp[0] = 1
for (const coin of coins) {
for (let i = coin; i <= amount; i++) {
dp[i] += dp[i - coin]
}
}
return dp[amount]
};
377. 组合总和IV
求排列的个数
五部曲:
- dp[i]: 凑成目标正整数为i的排列个数为dp[i]
- dp[i](考虑nums[j])可以由 dp[i - nums[j]](不考虑nums[j]) 推导出来。 因为只要得到nums[j],排列个数dp[i - nums[j]],就是dp[i]的一部分。
- 因为递推公式dp[i] += dp[i - nums[j]]的缘故,dp[0]要初始化为1,这样递归其他dp[i]的时候才会有数值基础。
- 如果求组合数就是外层for循环遍历物品,内层for遍历背包。如果求排列数就是外层for遍历背包,内层for循环遍历物品。
- 验证
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var combinationSum4 = function (nums, target) {
const dp = new Array(target + 1).fill(0)
dp[0] = 1;
for (let i = 1; i <= target; i++) {
for (const num of nums) {
if (num <= i) {
dp[i] += dp[i - num]
}
}
}
return dp[target]
};