本文最后更新于:2022年4月9日 中午
给定不同面额的硬币 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
Solution
思路参考:动态规划解题套路框架 、liuyubobobo
dp
数组的定义:当目标金额为 i
时,至少需要 dp[i]
枚硬币凑出。
dp
数组的迭代解法所需要的步骤最少,时间更短

| class Solution: def coinChange(self, coins: List[int], amount: int) -> int: dp = [amount+1]*(amount+1) dp[0] = 0 for i in range(len(dp)): for coin in coins: if (i-coin)<0: continue dp[i] = min(dp[i], 1+dp[i-coin]) return dp[amount] if dp[amount] != amount+1 else -1
|
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { private: vector<int> memo;
int go(const vector<int>& coins, int amount){ if(amount==0){ return 0; }
if(memo[amount] != -1) return memo[amount];
int res = INT_MAX; for(int i=0; i<coins.size(); ++i){ if(amount >= coins[i]) res = min(res, 1+go(coins, amount-coins[i])); } memo[amount]=res; return res; }
public: int coinChange(vector<int>& coins, int amount) { if(coins.size()==0 || amount<=0) return 0; memo = vector<int>(amount+1, -1); int res = go(coins, amount); return res; } };
|
| class Solution { public: int coinChange(vector<int>& coins, int amount) { if(coins.size()==0 || amount<=0) return 0; vector<int> dp(amount+1, amount+1); dp[0] = 0; for(int coin : coins) for(int j=coin; j<=amount; ++j) dp[j] = min(dp[j], dp[j-coin] +1); if(dp[amount]==amount+1) return -1; return dp[amount]; } };
|