题目描述
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
思路
这是一个完全背包问题,背包问题当满足:物品不限制放入背包的个数,就是完全背包问题。背包问题一般要注意两个顺序:
- 循环嵌套的顺序,是把遍历物品的循环放外层还是把遍历背包的循环放在外层。
- 遍历dp数组的先后顺序,是从前往后遍历还是从后往前遍历。
这道题使用一维dp,注意在遍历dp数组的时候要从前往后,因为一个物品可以放多次。
具体步骤
1 确定dp数组的意义
dp[j]表示当总金额为j时,最少用dp[j]枚硬币可以凑出来
2 确定状态转移方程
dp[j] = min{dp[j - coin] + 1} (coin <= j,且coin属于coins数组)
3 初始状态
由于这题是求最小值,所以初始值设置为正无穷,又根据状态转移方程可知,dp数组中下标较大的值是由下标较小的值+1得到,所以dp[0]初始值应该设置为0。
代码
class Solution {
public int coinChange(int[] coins, int amount) {
if (amount == 0) return 0;
int[] dp = new int[amount + 1];
//dp[j]表示要将总金额凑成amount所需要的最少硬币数
Arrays.fill(dp, Integer.MAX_VALUE);
dp[0] = 0;
for (int i = 0; i < coins.length; i++) {
for (int j = coins[i]; j <= amount; j++) {
if (dp[j - coins[i]] != Integer.MAX_VALUE) {
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
}
return dp[amount] == Integer.MAX_VALUE ? -1 : dp[amount];
}
}
标签:遍历,硬币,int,322,零钱,amount,背包,LeetCode,dp
From: https://www.cnblogs.com/zawaludo/p/18336537