Skip to content
本页目录

0518-零钱兑换II

https://leetcode.cn/problems/coin-change-2

给你一个整数数组 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

基本思路 【有问题】

求最值,动态规划 定义 dp 数组, dp[i] 表示当前 amount 凑齐的金币的方案数,默认初始化为0 如果 coins = [1,2,5] dp[i] = dp[i-1] +1, dp[i-2]+1, dp[i-5] +1 的和, 如果 i-coins 小于 0 则为负数 顺序循环,最后返回 dp[n]

测试用例
5
[1,2,5]
执行结果 :9
dp[0]=1
dp[1]=1
dp[2]=2
dp[3]=3
dp[4]=5
dp[5]=9
预期:4

因为这里使用了排列的方式,存在重复计算 比如 dp[3] = 3 是 dp[1] + 2 或者 dp[2] + 1,这两种其实是同一种组合 1,2  和 2,1 不符合题意

参考代码【有问题】

csharp
public class Solution {
    public int Change(int amount, int[] coins) {
    	int[] dp = new int[amount+1];
        dp[0] = 1;
    	for(int i=1; i<=amount; i++){
    		for(int j=0; j<coins.Length; j++){
    			if(i - coins[j] >=0){
    				dp[i] += dp[i - coins[j]];
    			}
    		}
    	}
    	return dp[amount];
    }
}

参考代码2【官方】

将 coins 移到外面,每种硬币就计算一次, 循环过第一个硬币之后,再循环第二个硬币,这样就不会出现 1,2 然后 2,1 这种情况了。 参考如下图:

csharp

public class Solution {
    public int Change(int amount, int[] coins) {
    	int[] dp = new int[amount+1];
        dp[0] = 1;
        for(int j=0; j<coins.Length; j++){
    		for(int i=coins[j]; i<=amount; i++){
    			if(i - coins[j] >=0){
    				dp[i] += dp[i - coins[j]];
    			}
    		}
    	}
    	return dp[amount];
    }
}

复习:2022-03-31 同样的错误再犯一次【需要复习】

csharp
public class Solution {
    public int Change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        //dp[i]表示使用coins凑成金额i的方法数
        //初始化
        dp[0] = 1; //使用 coins 里面的硬币凑成0的方法是1种,就是什么都不放
        for(int i=1; i<=amount; i++){
            for(int j=0; j<coins.Length; j++){
                if(i>=coins[j]){
                    dp[i]+=dp[i-coins[j]];
                }
            }
        }
        return dp[amount];
    }
}

复习:20220514 差点忘记

定义 dp[i] 表示使用 coins 凑成i的方法数

csharp
public class Solution {
    public int Change(int amount, int[] coins) {
        //dp[i]表示coins凑成i的方法数
        int[] dp = new int[amount+1];
        dp[0] = 1; //初始化,凑成0个硬币的方式是0个硬币凑成0元,所以是一种
        for(int i=0; i<coins.Length;i++){
            for(int j=1;j<=amount;j++){
                if(j>=coins[i]){
                    dp[j] += dp[j-coins[i]];
                }
            }
        }
        return dp[amount];
    }
}

复习:20220630

csharp
public class Solution {
    public int Change(int amount, int[] coins) {
        int[] dp = new int[amount+1]; //dp[j]表示凑成零钱的方法数
        dp[0] = 1; //凑成0元的方案数是1
        for(int i=0; i<coins.Length; i++){//遍历物品
            for(int j=1; j<=amount; j++){ //遍历背包
                if(j >= coins[i]){
                    dp[j]+=dp[j-coins[i]];
                }
            }
        }
        return dp[amount];
    }
}

Released under the MIT License.