322. Coin Change
322. Coin Change
1. 題目描述
題目鏈接
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:
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Example 2:
Input: coins = [2], amount = 3
Output: -1
Note:
You may assume that you have an infinite number of each kind of coin.
2. 題目分析
硬幣找零問題,經典的動態規劃問題。給定一個金額,和給定幾種面值確定的硬幣,并且硬幣數量無限,找出使用最少的硬幣數來湊齊想要的金額。
人類的的思維,肯定是,一開始使用最大面額的硬幣去算,然后多了就換小一點的面額,少了,就換大一點的面額,直到等于金額,或者發現無法湊齊整數的金額,則結束。但計算機無法像人類這樣智能,可以準確知道少了多少面額,然后搜索是否有相應的硬幣去湊。而是要一個個去試和比較,這樣的話時間復雜度更高,所以我們不采用這種方法。
根據條件找最優解,并且能夠不斷拆分成相同的小問題,所以動態規劃的思想,自上而下分析。比如說 coins = [1, 2, 5], amount = 11,既然我要湊11塊錢,首先我可以選擇面額為1, 2, 5是三種硬幣,那么如果我
>對金額11湊硬幣數
- 金額:11
| 1 | 10 | 1 |
| 2 | 9 | 1 |
| 5 | 6 | 1 |
>對金額10,9,6分別繼續湊硬幣數
- 金額:10
| 1 | 9 | 2 |
| 2 | 8 | 2 |
| 5 | 5 | 2 |
- 金額:9
| 1 | 8 | 2 |
| 2 | 7 | 2 |
| 5 | 4 | 2 |
- 金額:6
| 1 | 5 | 2 |
| 2 | 4 | 2 |
| 5 | 1 | 2 |
>對金額9,8,5分別繼續湊硬幣數
>對金額8,7,4分別繼續湊硬幣數
>對金額5,4,1分別繼續湊硬幣數
…
直到等于金額,或者發現無法湊齊整數的金額,則結束。
這是自上而下的分析思路,然后從分析過程也發現,很多金額會唄計算多遍,如果9,8,5等等,為了避免不必要的回溯,提高效率,使用空間換時間的方式,使用備忘錄法,自下而上計算前面金額所需要的硬幣數,然后再使用計算好的金額去計算大金額所需要的硬幣數,像這題,我們可以先計算金額為1,2,3,4,10分別所需要的最小硬幣數,那么不就直接可以統計出金額為11所需要的最小硬幣數了嗎?
3. 解決思路
狀態dp[value],表示金額為value時,所需要的最小硬幣數。那么它會等于dp[value-coins[j]]+1(0=<j<=n)
狀態轉移方程:dp[value] = Math.min(dp[value], dp[value-coins[j]]+1);
4. 代碼實現(java)
package com.algorithm.leetcode.dynamicAllocation;/*** Created by 凌 on 2018/12/15.* 描述:322. Coin Change*/ public class CoinChange {public static void main(String[] args) { // int[] coins = {1, 2, 5}; // int amount = 11;int[] coins = {2};int amount = 0;int result = coinChange(coins,amount);System.out.println(result);}public static int coinChange(int[] coins, int amount) {if (coins == null || coins.length==0 ){return -1;}//f(n) = min(f(n) , f(n - coins[i])+1 ) ,//dp[i]=j表示組成i元,最少需要j個硬幣int[] dp = new int[amount+1];//組成1元,2元,,,n元需要的最小硬幣數for (int value = 1; value <= amount; value++) {//這里必須設置為Integer.MAX_VALUE-1,而不是Integer.MAX_VALUE,因為后面有dp[i - coins[j]] + 1的操作,// 如果為MAX_VALUE,+1則為負數最小值dp[value] = Integer.MAX_VALUE -1;//遍歷所有價值的硬幣,找到符合組合的硬幣for (int j = 0; j < coins.length; j++) {if (value >= coins[j]){dp[value] = Math.min(dp[value], dp[value-coins[j]]+1);}}}return dp[amount] == Integer.MAX_VALUE-1 ? -1 : dp[amount];} }5. 拓展,求最大硬幣數
分析方法同求最小硬幣數。
狀態dp[value],表示金額為value時,所需要的最大硬幣數。那么它會等于dp[value-coins[j]]+1(0=<j<=n)
狀態轉移方程:dp[value] = Math.max(dp[value], dp[value-coins[j]]+1);
總結
以上是生活随笔為你收集整理的322. Coin Change的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Verilog HDL 快速入门
- 下一篇: edius 计算机配置,安装EDIUS