(LeetCode 322) Coin Change

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中的最小值是min ,那麼我們遍歷迭代的最高層數就是maxf=amount/min ,如果到了這個層數還沒有找到,那麼就不能拆分。

  1. 保留兩個隊列,先將amount減去coins中的值,並壓入到其中一個隊列pq1中。
  2. 將pq1中的值一個個彈出,並減去coins中的面值,壓入到pq2中。
  3. 將pq2中的值一個個彈出,並減去coins中的面值,壓入到pq2中。
  4. 循環2、3步,直到彈出的值爲0或者 迭代次數>maxf ,如果是彈出值爲0,那麼返回2、3步迭代次數。否則返回-1。

當然也很容易想到,超時了,畢竟遍歷數量是隨層數增加指數增長的。

上網一查,發現大家用的都是動態規劃DP,核心意思就是dp[n]=min(dp[n],dp[ncoins[m]]+1) ,然後從dp[1]迭代到dp[n] ,其實也好理解。但是我覺得這種方法時間消耗較高,大概是O(nm)
我想了想,BFS算法經過剪枝後最多遍歷次數也就是n 次,所以還是用BFS算法寫了。但是加入了剪枝操作,因爲我發現它的時間複雜度過高是因爲有重複的數值壓入隊列中,那麼,使用一個數組來標記每一個壓入值。如果當前壓入值已經被標記,那麼就不壓入該值。這樣一剪枝,那麼重複的數值就不會出現了,那麼最壞的遍歷就是amount0 ,也就是遍歷n次。

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

發佈了45 篇原創文章 · 獲贊 15 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章