1. 518. 零錢兌換 II
給定不同面額的硬幣和一個總金額。寫出函數來計算可以湊成總金額的硬幣組合數。假設每一種面額的硬幣有無限個。
輸入: amount = 5, coins = [1, 2, 5]
輸出: 4
解釋: 有四種方式可以湊成總金額:
5=5
5=2+2+1
5=2+1+1+1
5=1+1+1+1+1
暴力遞歸
索引index和cursum作爲可變參數,參與暴力遞歸
//暴力遞歸
class solution {
public:
int change(int amount, vector<int>& coins) {
if(amount<0)
return 0;
return p1(coins,0,amount);
}
int p1(vector<int>& coins,int index,int amount)// 不斷減少amout
{// 當前情況下返回的個數
int res=0;
if(index == coins.size())//最後一個了
return amount==0?1:0;
// 暴力,當前的位置選了幾次
for(int i=0;coins[index]*i <= amount;i++){
res+=p1(coins,index+1,amount-coins[index]*i);
return res;}
}
};
記憶化搜索(函數外加個傻緩存)
- 由可變參數構成一個結構(2個就是一個矩陣)(初始化,在遞歸函數之外)
- get 操作,看此次可變參數對應的位置,之前出現過沒
- put 操作,將運算得到的此次可變參數,對應的res弄給矩陣
class Solution {
public:
int change(int amount, vector<int>& coins) {
if(amount<0)
return 0;
vector<vector<int> > temp(coins.size()+1,vector<int>(amount+1,0));
return p1(coins,0,amount,temp);
}
int p1(vector<int>& coins,int index,int amount,vector<vector<int> >& temp)
{
int res=0;
if(index == coins.size())
res= amount==0?1:0;
else
{
int tempval=0;
for(int i=0;coins[index]*i<=amount;i++)
{
tempval=temp[index+1][amount-coins[index]*i];
// get 操作,get出來看之前是不是已經算出來了
if(tempval!=0)
res+= tempval==-1?0:tempval;
else
res+= p1(coins,index+1,amount-coins[index]*i,temp);
}
}
// put操作,將這次計算的res放到,由可變形參組成的矩陣裏面。
temp[index][amount]= res==0?-1:res;
return res;
}
};
動態規劃
class Solution {
public:
int change(int amount, vector<int>& coins) {
if (amount < 0 || (coins.size() == 0 && amount != 0))
return 0;
if (coins.size() == 0 && amount == 0)
return 1;
vector<vector<int> > dp(coins.size(), vector<int>(amount + 1, 0));
for (int i = 0; i < coins.size(); ++i)
dp[i][0] = 1;
for (int i = 0; i < amount + 1; i++)
{
if (i%coins[0] == 0)
dp[0][i] = 1;
else
dp[0][i] = 0;
}
for (int i = 1; i < coins.size(); ++i)
{
for (int j = 1; j < amount + 1; ++j)
{
// for(int k=0;k*coins[i]<=j;k++)//動態規劃
// {
// dp[i][j]+=dp[i-1][j-k*coins[i]];
// }
if (coins[i] <= j) //動態規劃改進
dp[i][j] = dp[i - 1][j] + dp[i][j - coins[i]];
else
dp[i][j] = dp[i - 1][j];
}
}
return dp[coins.size() - 1][amount];
}
};