零钱兑换||
题目
零钱兑换||
给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。
假设每一种面额的硬币有无限个。
题目数据保证结果符合 32 位带符号整数。
示例
![]() |
|---|
解题思路1
1.该题木我们可以使用递归算法进行暴力求解。
2.根据题目可以知道,每个硬币可以重复使用。
3.此时我们可以使用递归回溯算法。
for(int i = start; i < coins.size(); i++){
getNumberchange(coins, cnt, amount, value+coins[i], i);
}
4.其中cnt表示满足条件个数,coins表示硬币集合。amount表示目标金额。value+cons[i]:表示当前组合的和。i:表示下一次从什么面额金额开始。
实现代码
class Solution {
public:
void getNumberchange(const vector<int> & coins, int & cnt, int amount, int value, int start){
if(value >= amount) {
if(value == amount) cnt++;
return ;
}
for(int i = start; i < coins.size(); i++){
getNumberchange(coins, cnt, amount, value+coins[i], i);
}
}
int change(int amount, vector<int>& coins) {
int cnt = 0;
getNumberchange(coins, cnt, amount, 0, 0);
return cnt;
}
};
解题思路2
1.第二种方法,我们采用动态规划解题。
2.根据题目可知,每种面额的金币可以重复使用。
3.与传统0-1背包问题,我们可以将面额硬币重复使用。
//代码1
for(int k = coins[i]; k <= amount; k++){
dp[k] = dp[k] + dp[k-coins[i]];
}
//代码2
for(int k = amount; k >= coins[i]; k--){
dp[k] = dp[k] + dp[k-coins[i]];
}
4.代码1部分表示相同硬币使用金额可以反复使用。
5.代码2部分表示相同硬币使用时,只能使用一次。
实现代码
class Solution {
public:
int change(int amount, vector<int>& coins) {
vector<unsigned long long> dp(amount+1, 0);
dp[0] = 1;
for(int i = 0; i < coins.size(); i++){
for(int k = coins[i]; k <= amount; k++){
dp[k] = dp[k] + dp[k-coins[i]];
}
}
return dp[amount];
}
};


浙公网安备 33010602011771号