【温故知新】`518. 零钱兑换 II` 完全背包问题组合解-动态规划实现

506 阅读1分钟

题目描述

给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。

请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。

假设每一种面额的硬币有无限个。 

题目数据保证结果符合 32 位带符号整数。

 

示例 1:

输入:amount = 5, coins = [1, 2, 5] 输出:4 解释:有四种方式可以凑成总金额: 5=5 5=2+2+1 5=2+1+1+1 5=1+1+1+1+1 示例 2:

输入:amount = 3, coins = [2] 输出:0 解释:只用面额 2 的硬币不能凑成总金额 3 。 示例 3:

输入:amount = 10, coins = [10] 输出:1  

提示:

1 <= coins.length <= 300 1 <= coins[i] <= 5000 coins 中的所有值 互不相同 0 <= amount <= 5000

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

image.png

完全背包🎒-组合数问题

完全背包🎒问题典型特点是:物品数量不限; 完全背包四部曲:

  • 定义dp数组:
    • dp[j]代表兑换零钱总金额amount的硬币组合数;
  • 递推公式:
    • dp[j] 上次递推结果加上dp[j-coins[i]]所有组合数;
    • 所以公式为:dp[j]+=dp[j-coins[i]]
  • dp 数组初始化
    • 从题意入手:dp[0],表示凑成零钱总金额0元的组合数为1,
    • dp[0]=1,为递推公式的基础;
    • 下标非0的dp[j],应初始化为0,这样在计算dp[j]+dp[j-coins[i]]不会影响到dp的初始计算;
  • 遍历物品还是背包容量的for循环顺序,是否影响结果
    • 本题是求零钱兑换的组合数,与排列顺序无关; 我们来看先遍历物品再遍历容量的代码:
    for (int i = 0; i < coins.length); i++) { // 遍历物品
      for (int j = coins[i]; j <= amount; j++) { // 遍历背包容量
          dp[j] += dp[j - coins[i]];
      }
    }
    
    
    这时候计算dp[j]的顺序一定是按照coins[]数组顺序遍历; 如:coins[0] = 1,coins[1] = 2。组合为{1,2};而不会出现{2,1} 我们再来看看先遍历容量,在遍历物品的代码:
     for(let j=0;j<=amount;j++){ // 先遍历容量
       for(let i=0;i<coins.length;i++){  // 后遍历物品
          if(j-coins[i]>=0){
              dp[j]+=dp[j-coins[i]]
            }
        }
      } 
    

这时候计算出来的每一个容量dp[j],都包含{1,2}和{2,1}这样的排列之和的计算;

总结:

在求装满背包🎒问题顺序关键在于:

  • 如果求组合数就是外层for循环遍历物品,内层for遍历背包。
  • 如果求排列数就是外层for遍历背包,内层for循环遍历物品。

代码

/**
 * @param {number} amount
 * @param {number[]} coins
 * @return {number}
 */
var change = function(amount, coins) {
  // 完全背包问题;求硬币组合数、,初始化为0; 每一种面额硬币无限
  let n=coins.length;
  //1、初始化 初始化dp容量,amount===0时,组合数为0;
  let dp=new Array(amount+1).fill(0)
  dp[0]=1;
  for(let i=0;i<n;i++){
      for(let j=coins[i];j<=amount;j++){
          dp[j]+=dp[j-coins[i]]
      }
  }// end of for 
  return dp[amount]
};

背包问题

【温故知新】322. 零钱兑换 动画演示-完全背包问题最小解-动态规划实现