Appearance
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];
}
}
AlgoPress