Q:
You are given coins of different denominations and a total amount of money amount. Write a function to compute the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
Example 1:
coins = [1, 2, 5], amount = 11
return 3 (11 = 5 + 5 + 1)
Example 2:
coins = [2], amount = 3
return -1.
Note:
You may assume that you have an infinite number of each kind of coin.
也就是給你一些面值的硬幣,然後給你一個數,問這個數能不能由給你提供的面值累加得到,並且問需要的最少硬幣個數。
每個面值的硬幣假設有無限個。
solution:
哎,感覺自己還是太差,這麼個問題也寫了一個多少小時。
第一眼看到這個問題,我首先想到解法是BFS算法,已知coins中的最小值是
- 保留兩個隊列,先將amount減去coins中的值,並壓入到其中一個隊列pq1中。
- 將pq1中的值一個個彈出,並減去coins中的面值,壓入到pq2中。
- 將pq2中的值一個個彈出,並減去coins中的面值,壓入到pq2中。
- 循環2、3步,直到彈出的值爲0或者 迭代次數
>maxf ,如果是彈出值爲0,那麼返回2、3步迭代次數。否則返回-1。
當然也很容易想到,超時了,畢竟遍歷數量是隨層數增加指數增長的。
上網一查,發現大家用的都是動態規劃DP,核心意思就是
我想了想,BFS算法經過剪枝後最多遍歷次數也就是
class Solution {
public:
queue<int>pq1;
queue<int>pq2;
int coinChange(vector<int>& coins, int amount) {
if(coins.size()==0)return -1;
if(amount==0)return 0;
int *flag =new int[amount];
int min = coins[0];
for(int i=0;i<coins.size();i++){
if(coins[i]<min)
min=coins[i];
pq1.push(amount-coins[i]);
if(amount-coins[i]>=0)flag[amount-coins[i]]=-1;
}
for(int j=1;j<=amount/min;j++){
queue<int> &pq3=(j%2!=0)?pq1:pq2;
queue<int> &pq4=(j%2!=0)?pq2:pq1;
while(!pq3.empty()){
int res = pq3.front();
pq3.pop();
if(res<0)continue;
if(res==0)return j;
for(int k=0;k<coins.size();k++){
if(flag[res-coins[k]]==-1||res-coins[k]<0) continue;
pq4.push(res-coins[k]);
flag[res-coins[k]]=-1;
}
}
}
return -1;
}
};
事實證明,時間消耗比起DP確實小了很多。這個是116ms,DP是159ms。
Reference Link:
http://blog.csdn.net/sbitswc/article/details/50505003