题目:322. 零钱兑换
方法一:动态规划dp+完全背包问题。
Acwing算法基础课 第五讲 动态规划:前四题都是背包问题
C++版本:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
//状态f[i]表示:凑成金额i的最少硬币个数
vector<int> f(amount+1,amount+10);//置为amount+10表示不可能组合成该金额
//初始化边界
f[0]=0;
//第一层for循环枚举所有硬币
for(int i=0;i<coins.size();i++){
//完全背包问题
for(int j=coins[i];j<=amount;j++){
f[j]=min(f[j],f[j-coins[i]]+1);
}
}
return f[amount]==amount+10 ? -1: f[amount];
}
};
JAVA版本:
class Solution {
public int coinChange(int[] coins, int amount) {
//状态f[i]表示:凑成金额i的最少硬币个数
int[] f=new int[amount+1];
//置为amount+1表示不可能组合成该金额
Arrays.fill(f,amount+10);
//初始化边界
f[0]=0;
//第一层for循环枚举所有硬币
for(int i=0;i<coins.length;i++){
//完全背包问题
for(int j=coins[i];j<=amount;j++){
f[j]=Math.min(f[j],f[j-coins[i]]+1);
}
}
return f[amount]==amount+10? -1:f[amount];
}
}
第一层for循环也可以枚举amount
C++版本:
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> f(amount+1,amount+10);
f[0]=0;
//第一层for循环枚举amount
for(int i=1;i<=amount;i++){
for(int j=0;j<coins.size();j++){
if(coins[j]<=i) f[i]=min(f[i],f[i-coins[j]]+1);
}
}
return f[amount]==amount+10 ? -1: f[amount];
}
};
JAVA版本:
class Solution {
public int coinChange(int[] coins, int amount) {
int[] f=new int[amount+1];
Arrays.fill(f,amount+10);
f[0]=0;
//第一层for循环枚举amount
for(int i=1;i<=amount;i++){
for(int j=0;j<coins.length;j++){
if(coins[j]<=i) f[i]=Math.min(f[i],f[i-coins[j]]+1);
}
}
return f[amount]==amount+10? -1:f[amount];
}
}
方法二:递归+记忆化dfs。
C++版本:
class Solution {
public:
//记忆化数组sta
vector<int> sta;
int dfs(vector<int>& coins, int amount){
//小于0,表明不符合
if(amount<0) return -1;
//等于0,表明符合
if(amount==0) return 0;
//遍历过
if(sta[amount]!=0) return sta[amount];
//最小值
int mn=INT_MAX;
//枚举所有可能的硬币
for(int i=0;i<coins.size();i++){
int tmp=dfs(coins,amount-coins[i]);
//-1表明该条路线不可
if(tmp==-1) continue;
mn=min(mn,tmp+1);
}
return sta[amount]= mn==INT_MAX? -1:mn;
}
int coinChange(vector<int>& coins, int amount) {
sta.resize(amount+1);
//memset(sta,-1,sizeof sta);
return dfs(coins,amount);
}
};
JAVA版本:
class Solution {
//记忆化数组sta
private int[] sta;
private int dfs(int[] coins, int amount){
//小于0,表明不符合
if(amount<0) return -1;
//等于0,表明符合
if(amount==0) return 0;
//遍历过
if(sta[amount]!=0) return sta[amount];
//最小值
int mn=Integer.MAX_VALUE;
//枚举所有可能的硬币
for(int i=0;i<coins.length;i++){
int tmp=dfs(coins,amount-coins[i]);
//-1表明该条路线不可
if(tmp==-1) continue;
mn=Math.min(mn,tmp+1);
}
return sta[amount]= mn==Integer.MAX_VALUE? -1:mn;
}
public int coinChange(int[] coins, int amount) {
sta=new int[amount+1];
//置为0,表示没有遍历过
Arrays.fill(sta,0);
return dfs(coins,amount);
}
}