518. 零钱兑换 II

这篇博客探讨了一种经典的计算机科学问题——硬币找零问题。通过两种不同的动态规划实现,详细解释了如何用JavaScript编写算法来找出给定硬币面额和总金额下,组合数的所有可能。博客内容涵盖了错误思路分析以及正确的状态转移方程,帮助读者理解动态规划在解决此类问题中的应用。
摘要由CSDN通过智能技术生成

题目

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

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

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

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

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

示例

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

错误思路

/**
 * @param {number} amount
 * @param {number[]} coins
 * @return {number}
 */
var change = function(amount, coins) {
    let dp = new Array(amount + 1).fill(0);
    dp[0] = 1;
    for(let i = 1; i <= amount; i++){
        for(let index=0;index<coins.length;index++){
            if(i-coins[index]>=0){
                dp[i]+=dp[i-coins[index]]
            }
        }
    }
    return dp[amount];
};

 答案

dp三部曲,a.定义子问题,b. 定义状态数组,c. 定义状态转移方程。
用前k的硬币凑齐金额i,要分为两种情况考虑,

  • 一种是没有用前k-1个硬币就凑齐了,
  • 一种是前面已经凑到了i-k,现在就差第k个硬币了。

状态数组就是DP[k][i], 即前k个硬币凑齐金额i的组合数。

这里不再是一维数组,而是二维数组。第一个维度用于记录当前组合有没有用到硬币k,第二个维度记录现在凑的金额是多少?如果没有第一个维度信息,当我们凑到金额i的时候,我们不知道之前有没有用到硬币k。

/**
 * @param {number} amount
 * @param {number[]} coins
 * @return {number}
 */
var change = function(amount, coins) {
    let dp = new Array(amount + 1).fill(0);
    dp[0] = 1;
    for(let i = 0; i < coins.length; i++){
        for(let j = coins[i]; j <= amount; j++){
            dp[j] += dp[j - coins[i]];
        }
    }
    return dp[amount];
};

/**
 * @param {number} amount
 * @param {number[]} coins
 * @return {number}
 */
var change = function (amount, coins) {
    let K = coins.length + 1;
    let I = amount + 1;
    /*js定义并初始化二维数组*/
    let dp = new Array();
    for (let k = 0; k < K; k++) {
        dp[k] = new Array();
        for (let i = 0; i < I; i++) {
            dp[k][i] = 0;
        }
    }
    //base case
    for (let k = 0; k <= coins.length; k++) {
        dp[k][0] = 1;
    }
    for (let k = 1; k <= coins.length; k++) {
        for (let i = 1; i <= amount; i++) {
            if (i >= coins[k - 1]) {
                dp[k][i] = dp[k][i - coins[k - 1]] + dp[k - 1][i];
            } else {
                dp[k][i] = dp[k - 1][i];
            }
        }
    }
    return dp[coins.length][amount];
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值