「这是我参与2022首次更文挑战的第8天,活动详情查看:2022首次更文挑战」。
322. 零钱兑换
题目描述
给你一个整数数组 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
解析
/**
* @brief 动态规划 - 背包
* 1、确定dp数组以及下标含义
* dp[j]: 凑够金额为 j 时所需要金币数量最少个数为 dp[j]。
* 2、确定递推公式
* 凑够金额为 j - coins[i] 的最少金币个数为 dp[j- coins[i]] .
* 那么再加上一个金币 coins[i]即 dp[j-coins[i]]+1 就可以得到凑够金金额为 j 的金币的个数
* 此时需要考虑两种情况:dp[j]和dp[j-coins[i]]+1,所需要的是其中较小的值。
* 所以 dp[j] = min(dp[j],dp[j-coins[i]]+1)
* 3、初始化dp数组
* dp[0] = 0 : 凑够金额为0的最少金币数 , 作为dp数组的基础。
* 4、确定遍历顺序
* 求组合数就是:先遍历物品,再遍历背包
* 求排列数就是:先遍历背包,再遍历物品
* 本题要求组合数,所以选择先遍历物品,再遍历背包。
*/
代码
class Solution
{
public:
int coinChange(vector<int> &coins, int amount)
{
// 考虑到递推公式的特性,将dp数组初始化为最大整数值
vector<int> dp(amount + 1, INT32_MAX);
// dp[0]再初始化为0
dp[0] = 0;
// 求组合数
// 先遍历物品
for (int i = 0; i < coins.size(); i++)
{
// 再遍历背包
for (int j = coins[i]; j <= amount; j++)
{
if (dp[j - coins[i]]!=INT32_MAX){
// 递推公式
dp[j] = min(dp[j], dp[j - coins[i]] + 1);
}
}
}
if(dp[amount] == INT32_MAX){
return -1;
}
return dp[amount];
}
}