题目描述:
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/coin-change
思路:(动态规划)
以下是典型的动态规划解题流程:
状态定义
设dp[i] 表示凑金额 i 需要的最少硬币个数
转移方程
设要凑的金额为amount,dp[amount] 即为所求。
以coins = [1, 2, 5], amount = 11为例,要求组成11是所用的硬币最少,我们从最后一个硬币的可能性进行讨论:
若最后一个硬币是1,最少硬币数是【组成10的最少硬币数】+ 1枚(1块硬币)
若最后一个硬币是2,最少硬币数是【组成9的最少硬币数】+ 1枚(2块硬币)
若最后一个硬币是5,最少硬币数是【组成6的最少硬币数】+ 1枚(5块硬币)
dp[amount] 即为以上3中情况的最小值。继续推,要组成金额 10 的硬币最少,最成9的硬币最少······。最终我们可以推到组成2,1 所需的硬币最少。所以我们用自底向上的策略,将组成1-11金额的最少硬币数依次求出,对于每个金额我们都要比较最后一个硬币是不同面值时的情况,选出最小值。
初始状态
dp[0] = 0; //凑金额 0 需要的最少0个硬币
返回值
返回dp数列的最后一个元素即为最少硬币个数
class Solution {
public:
int coinChange(vector<int>& coins, int amount) {
vector<int> dp(amount+1,amount+1);
//dp[i] 表示凑金额i需要的最少硬币个数
//base case
dp[0] = 0;
for(int i=1; i<dp.size(); ++i)
{
for(int coin : coins){
if(coin <= i)
dp[i] = min(dp[i-coin]+1,dp[i]);
}
}
return (dp[amount]==amount+1)? -1:dp[amount];
}
};
效率并不高。应该是贪心+DFS效率更好。目前在做动态规划,之后会再补充次解法。。

这篇博客介绍了如何使用动态规划解决LeetCode 322题——零钱兑换问题。当给定不同面额的硬币和一个总金额时,该文探讨了如何计算凑成总金额所需的最少硬币数量,并提供了示例及解题思路。动态规划解法通过定义状态和转移方程,自底向上计算出组成目标金额的最小硬币数。
2198

被折叠的 条评论
为什么被折叠?



