518. 零钱兑换 II

233 阅读2分钟

思路:动态规划

  • 完全背包
  • dp[j]:凑成总金额j的货币组合数为dp[j]
  • 递推公式:dp[j] += dp[j - coins[i]];
    • dp[j] (凑成总金额j的货币组合数) 就是所有的dp[j - coins[i]](i变化)相加。
    • 比如,凑5块钱的方法数 = 凑4块钱的方法数(再选一元硬币)+ 凑3块钱的方法数(再选2元硬币) + 凑0块钱的方法数(再选5元硬币)
  • dp数组初始化
    • 首先dp[0]一定要为1,从dp[i]的含义上来讲就是,凑成总金额0的货币组合数为1。
    • 下标非0的dp[j]初始化为0,这样累计加dp[j - coins[i]]的时候才不会影响真正的dp[j]
  • 由于本题找组合数,所以外层循环要遍历物品,内层遍历背包容量,不可更换。 如果外层遍历背包容量,求出来的是排列数。
    • 外层遍历coins:假设:coins[0] = 1,coins[1] = 5。那么就是先把1加入计算,然后再把5加入计算,得到的方法数量只有{1, 5}这种情况。而不会出现{5, 1}的情况。
    • 外层遍历amount:背包容量的每一个值,都是经过 1 和 5 的计算,包含了{1, 5} 和 {5, 1}两种情况。
class Solution {
    public int change(int amount, int[] coins) {
        int length = coins.length;
        int[] dp = new int[amount + 1];//新建数组时已经将非0位初始化为0.
        dp[0] = 1;
        for (int i = 0; i < length; i++) {
            for (int j = 1; j <= amount; j++) {
                if (j - coins[i] >= 0) {
                    //表示对于i种硬币的情况下,总额为amount的组合数量
                    dp[j] = dp[j] + dp[j - coins[i]]; //滚动更新
                }
            }
        }
        return dp[amount];
    }
}