给定不同面额的硬币 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 <= 231 - 1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:本题是动态规划题,我们假设:f(X) = 最少用多少枚硬币拼出X
,因为如果能拼出的话,最后一枚硬币肯定是从coins
中的一个,所以转移方程为:
f[i] = min(f[i-coins[0]]+1,...,f[i-coins[n-1]]+1)
。
而边界条件为:f(0) = 0
时间复杂度:O(amount*n) n为硬币种数
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> f(amount + 1,0);
int n = coins.size();//硬币的种数
for(int i = 1;i <= amount;++i)//拼amount钱数 总共需要迭代amount步
{
f[i] = INT_MAX; //最初设定为无穷大
//下面枚举的就是最后一步
// f[i] = min(f[i-coins[0]]+1,...,f[i-coins[n-1]]+1)
for(int j = 0;j < n;++j)
{
//1 是确保我们要拼的钱数大于当前选的硬币
//2 是确保编程中INT_MAX不越界
if(i>=coins[j] && f[i-coins[j]] != INT_MAX)
f[i] = min(f[i - coins[j]]+1,f[i]);
}
}
if(f[amount] == INT_MAX)
return -1;
return f[amount];
}
};