提示:这是一个完全背包问题
方法一:
class Solution {
public int coinChange(int[] coins, int amount) {
if(coins == null || coins.length == 0 || amount == 0) {
return 0;
}
int len = coins.length;
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
dp[0] = 0;
for(int i = 1; i <= amount; i++) {
for(int j = 0; j < len; j++) {
if(coins[j] <= i) {
dp[i] = Math.min(dp[i], dp[i - coins[j]]+1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
注意:
完全背包问题和0-1背包问题的区别和解法上异同:
完全背包是可以重复选择物品的,如本题中的硬币是可以重复选择的,而0-1背包问题是不可以重复选择物品的,回忆之前的0-1背包问题,为了解决重复选择物品的问题,我们在遍历的时候是从后往前遍历这样就不会对物品进行重复的选择,而在完全背包问题中我们可以重复选择,于是便从前往后开始遍历,下图展示了一个例子,并且我们可以从中看到重复取数的情况。
方法二:
class Solution {
public int coinChange(int[] coins, int amount) {
if(coins == null || coins.length == 0 || amount == 0) {
return 0;
}
int[] dp = new int[amount + 1];
dp[0] = 0;
for(int coin : coins) {
for(int i = coin; i <= amount; i++) {
if(i == coin) {
dp[i] = 1;
}else if(dp[i] == 0 && dp[i - coin] != 0) {
dp[i] = dp[i - coin] +1;
}else if(dp[i - coin] != 0){
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
}
return dp[amount] == 0 ? -1 : dp[amount];
}
}