跟着carl学算法,本系列博客仅做个人记录,建议大家都去看carl本人的博客,写的真的很好的!
代码随想录
LeetCode: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
- 本题求的是最少硬币数,既不是排列问题也不是组合问题,所以两个
for
循环的顺序都可以 dp[j]
含义:装满容量为j
的背包的最少硬币数- 注意非
0
下标的初始值需要为Integer.MAX_VALUE
,0
下标的初始为0
- 递推公式:
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1)
,即nums[i]
装还是不装 - 如果
dp[j - coins[i]] == maxValue
则不符合,需要剔除,递推公式会溢出
public int coinChange(int[] coins, int amount) {int[] dp = new int[amount + 1];int maxValue = Integer.MAX_VALUE;// 0下标需要初始话为0, 非0下标初始化为最大值,因为下面求的是 Math.minArrays.fill(dp, maxValue);dp[0] = 0;for (int i = 0; i < coins.length; i++) {for (int j = coins[i]; j <= amount; j++) {// 注意这个if,如果dp[j - coins[i]] == 最大值(那么再加1就会溢出!)// 即选择nums[i]也到不了amount,只有不是最大值时才考虑if (dp[j - coins[i]] != maxValue)dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);}}return dp[amount] == maxValue ? -1 : dp[amount];}