完全背包问题
从1到amount,每个数把每个硬币减个遍,取他们中的最小值。
一开始我犯了个低级错误,把硬币小到大排序,然后从后往前遍历,相减大于等于零就停下。这样是错的,amount小还好,如果amount很大的话,结果可能是错的。所以要遍历所有硬币,取最小值。
class Solution {
public int coinChange(int[] coins, int amount) {
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 1);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int coin : coins) {
if (i - coin >= 0) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
}
return dp[amount] > amount ? -1 : dp[amount];
}
}
其实这道题最难的点是,coins = [2], amount = 3,或者coins = [2], amount = 1,要返回-1,怎么办?
- 如果硬币凑不整
amount,必定有某个dp[i]是未修改过的。比如上面例子的dp[1],均为初始值。 - 如果硬币都是一块钱,那么肯定有
dp[amount] == amount。
所以我们可以用amount + 1初始化dp数组(而不是amount,上述第二点),如果有某个dp[i]未修改过,最终dp[amount] > amount