题目链接
零钱兑换
题目描述
注意
- 至少有一种硬币
- 最终返回的是总金额所需的最少硬币数
- 可以认为每种硬币的数量是无限的
- 1 <= coins[i] <= 231 - 1
解答思路
- 采用动态规划从总金额为0开始推算出总金额为amount所需的最少硬币数
代码
public class Solution {
public int coinChange(int[] coins, int amount) {
// dp数组记录从0到amount金额所需的最少硬币个数,初始值设置为max
int max = amount + 1;
int[] dp = new int[max];
Arrays.fill(dp, max);
// 当总金额为0时,最少的硬币个数就是0
dp[0] = 0;
// 从金额1推算到金额amount所需的最少硬币个数
for (int i = 1; i <= amount; i++) {
// 遍历数组中的硬币面额
for (int j = 0; j < coins.length; j++) {
if (coins[j] <= i) {
// 金额i所需的最少硬币个数,只有在(i - coins[j] >= 0)时才进入判断
// 如果没有硬币金额可以组合成i - coins[j],则dp[i - coins[j]]的值大于amount,对后续结果没影响
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
关键点
- 将dp数组的初始值设置为amount + 1,因为硬币的最小面额也是1,如果全是由1组成的总金额,所需要的最多硬币数也只有amount,在最终结果的判断中,如果dp[amount]的值大于amount,则说明没有任何一种硬币的组合可以达到总金额,此时应返回-1
- 当总金额amount为0时,所需的最少硬币数也是唯一一种组合就是0个硬币
- 对每个金额i,都要将i减去硬币数组中的所有面额后的dp值进行判断,找到其中的最小值,如果i减去某个硬币的面额后小于0,则说明该硬币无法组合成总金额,直接跳过不进行判断