1. 程式人生 > 其它 >劍指 Offer II 103. 最少的硬幣數目(動態規劃)

劍指 Offer II 103. 最少的硬幣數目(動態規劃)

劍指 Offer II 103. 最少的硬幣數目

給定不同面額的硬幣 coins 和一個總金額 amount。編寫一個函式來計算可以湊成總金額所需的最少的硬幣個數。如果沒有任何一種硬幣組合能組成總金額,返回 -1

你可以認為每種硬幣的數量是無限的。

 

示例 1:

輸入:coins = [1, 2, 5], amount = 11
輸出:3 
解釋:11 = 5 + 5 + 1

示例 2:

輸入:coins = [2], amount = 3
輸出:-1

示例 3:

輸入:coins = [1], amount = 0
輸出:0

示例 4:

輸入:coins = [1], amount = 1
輸出:1

示例 5:

輸入:coins = [1], amount = 2
輸出:2

 

提示:

  • 1 <= coins.length <= 12
  • 1 <= coins[i] <= 231 - 1
  • 0 <= amount <= 104

動態規劃解法思路:

1、確定狀態:

  1)最後一步(最優策略中使用的最後一枚硬幣ak),其中最後一枚硬幣ak可以為1、2、5;

  2)  子問題(最少個數的硬幣拼出更小的面值11 - ak);

2、轉移方程:

  f[x] = min(f[x -1] + 1, f[x -2] + 1, f[x - 5] + 1);

3、初始條件和邊界情況:

  f[0] = 0,如果不能拼出y,f[y] = 正無窮;

4、計算順序:

  f[0],f[1],f[2],... ...

 1 class Solution {
 2 public:
 3     static constexpr int MAX_INF = 0x3F3F3F3F;
 4     int coinChange(vector<int>& coins, int amount) {
 5         int num = coins.size();
 6         vector<int> dp(amount + 1, MAX_INF);
 7
dp[0] = 0; 8 // 可以湊成總金額為i所需的最少硬幣個數為dp[i] 9 for (int i = 1; i <= amount; i++) { 10 // 選擇最後一枚硬幣 11 for (int j = 0; j < num; j++) { 12 if (i >= coins[j]) { 13 dp[i] = min(dp[i], dp[i - coins[j]] + 1); 14 } 15 } 16 } 17 return ((dp[amount] == MAX_INF) ? -1 : dp[amount]); 18 } 19 };