给你一个整数数组 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
Java代码1:完全背包、背包放入硬币的最小个数
背包:金额 amout
物品:零钱数 coins
dp[j]: 当背包容量为j时(最后一定能装满),能放入硬币的最小个数
public int coinChange(int[] coins, int amount) {
int[] dp= new int[amount + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int num : coins) {
for (int j = num; j <= amount; ++j) { // 硬币价值 <-> 背包容量、dp[]为最小硬币数
if (dp[j - num] != Integer.MAX_VALUE) { // [2] 3 dp[2]==1,dp[3] = min(dp[3], dp[1]+1)(就是说你不能只拿一个2,去装满背包容量为3的)
dp[j] = Math.min(dp[j], dp[j - num] + 1); // dp:[0, MAX, 1, MAX, MAX, AMX, MAX, MAX],我不能拿一个硬币2去装满背包3!往前查找dp[j]若为MAX,说明背包j是不能通过硬币装满的!
} // 1 代表什么? 答:代表放入的硬币个数为1;
} // 放入什么dp[]就代表什么!
} // 放入这个物品的数量 = 除去num的数量 + 新放入的 1 数量
// 像:(1) dp[j] = Math.max(dp[j], dp[j - num] + num);
// (2) dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]); 都是这个意思
// 都是在比较大小,一个对比的是:物品个数,一个对比的是:放入一个个物品对应的价值。
// 最后的核心都是一样的!
// 所以它们初始化 dp 全为 0;而排列数、组合数就不 dp[j - num] + 1,含义不一样。
// (1) 和 (2) 只要 bagSize 和 num 属性一致就 ok:
// num 与 bagSize 都是同属性;weight[i] 和 bagSize背包容量 也是同属性!
// 就只是用来判断:放与不放:dp[j - num] dp[j]
// 至于后面加的什么,可以是:物品个数 1、num、1个物品对应的 value[i]
// 这些就代表 dp[j] 的含义:装满背包的最小物品数、用能num去装背包 能装的最大和、背包能装的最大价值
if (dp[amount] == Integer.MAX_VALUE) { // 无法装满
return -1;
}
return dp[amount];
}