LeetCode_518_零钱兑换 II
原创
©著作权归作者所有:来自51CTO博客作者晴天码字的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目描述:
给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。
示例 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
注意:
你可以假设:
0 <= amount (总金额) <= 5000
1 <= coin (硬币面额) <= 5000
硬币种类不超过 500 种
结果符合 32 位符号整数
思路1:建立一个森林,此森林中子节点的权值不能小于父节点的权值,这样可以避免重复计算的情况,递归的写法虽然没有问题,但是会发生超时
class Solution {
public:
void DFS(vector<int>& coins,int amount,int &num,int &pre){
if(amount<=0)
return ;
for(int coin:coins){
if(coin>amount)
continue;
if(coin==amount&&coin>=pre){
num++;
pre=coin;
}
if(coin>=pre)
DFS(coins,amount-coin,num,pre);
}
}
int change(int amount, vector<int>& coins) {
int num=0;
sort(coins.begin(),coins.end());//按照非递减排序
int pre=coins[0];
DFS(coins,amount,num,pre);
return num;
}
};
思路2:动态规划
状态转移方程
dp[j]=dp[j-coin[0]]+dp[j-coin[1]]+dp[j-coin[2]]…
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<int> dp(amount+1);//vector 可以改变长度,没有限制,int dp[amount+1]就超过限制
dp[0]=1;
for(int i=0;i<coins.size();i++){
for(int j=1;j<=amount;j++){
if(j>=coins[i])
dp[j]+=dp[j-coins[i]];
}
}
return dp[amount];
}
};