322.零錢兌換(動態規劃和貪心)

322. 零錢兌換#

給定不一樣面額的硬幣 coins 和一個總金額 amount。編寫一個函數來計算能夠湊成總金額所需的最少的硬幣個數。若是沒有任何一種硬幣組合能組成總金額,返回 -1。網絡

來源:力扣(LeetCode)
連接:https://leetcode-cn.com/problems/coin-change
著做權歸領釦網絡全部。商業轉載請聯繫官方受權,非商業轉載請註明出處。函數

基本是按照這篇題解的思路code

貪心
11. 想要總硬幣數最少,確定是優先用大面值硬幣,因此對 coins 按從大到小排序
12. 先丟大硬幣,再丟會超過總額時,就能夠遞歸下一層丟的是稍小面值的硬幣排序

乘法對加法的加速
21. 優先丟大硬幣進去嘗試,也不必一個一個丟,能夠用乘法算一下最多能丟幾個遞歸

k = amount / coins[c_index] 計算最大能投幾個
amount - k * coins[c_index] 減去扔了 k 個硬幣
count + k 加 k 個硬幣

若是由於丟多了致使最後沒法湊出總額,再回溯減小大硬幣數量

最早找到的並非最優解
31. 注意不是現實中發行的硬幣,面值組合規劃合理,會有奇葩狀況
32. 考慮到有 [1,7,10] 這種用例,按照貪心思路 10 + 1 + 1 + 1 + 1 會比 7 + 7 更早找到
33. 因此仍是須要把全部狀況都遞歸完leetcode

ans 瘋狂剪枝
41. 貪心雖然得不到最優解,但也不是沒用的
42. 咱們快速算出一個貪心的 ans 以後,雖然還會有奇葩狀況,可是絕大部分普通狀況就能夠瘋狂剪枝了get

做者:ikaruga
連接:https://leetcode-cn.com/problems/coin-change/solution/322-by-ikaruga/
來源:力扣(LeetCode)
著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。io

class Solution {
    private int min=Integer.MAX_VALUE;
    public int coinChange(int[] coins, int amount) {
        if(coins==null||coins.length==0)
            return -1;
        Arrays.sort(coins);
        helper(coins,0,coins.length-1,amount);
        return min==Integer.MAX_VALUE?-1:min;
    }
    public void helper(int[] coins,int res,int index,int all)
    {
        if(all==0)
        {
            min=Math.min(res,min);
            return ;
        }
        if(index<0) //說明這種移動不能獲得一個有效值,因此直接返回。
            return;
        for(int i=all/coins[index];i>=0&&res+i<min;i--) //這裏i取到0就會跳到下一個位置,就能夠在最上層實現移動。
        {
            helper(coins,res+i,index-1,all-i*coins[index]);
        }
    }
}

使用dp來作,讓amount從小到大增長,使得後面的dp值複用前面的class

class Solution {
    public int coinChange(int[] coins, int amount) {
        if(coins==null||coins.length==0)
            return -1;
       int[] dp=new int[amount+1];
       for(int i=1;i<dp.length;i++)
            dp[i]=Integer.MAX_VALUE;
       for(int i=1;i<=amount;i++)
       {
           int min=Integer.MAX_VALUE;
           for(int j=0;j<coins.length;j++)
           {
               if(i-coins[j]>=0&&(dp[i-coins[j]]!=Integer.MAX_VALUE))
                    min=Math.min(dp[i-coins[j]]+1,min);
           } 
           dp[i]=min; 
       }

       return dp[amount]==Integer.MAX_VALUE?-1:dp[amount];
    }
 
}
相關文章
相關標籤/搜索