
思路:动态规划
- 每种物品可以重复无限次使用,为完全背包问题
dp[i]
:凑足总额为i
所需钱币的最少个数为dp[i]
- 递推公式:
dp[i] = min(dp[i - coins[j]] + 1, dp[i])
;
- 凑足总额为
i-coins[j
]的最少个数为dp[i-coins[j]]
,再加上一个钱币coins[j]
即dp[i-coins[j]]+1
就是dp[i]
dp[i]
要取所有dp[i-coins[j]] + 1
中最小的,采取滚动数组的方式来计算min。
- 由于是找个数,排列or组合都可以,所以本题内外层遍历顺序可以交换。
写法1:外层遍历amount,内层遍历coins
class Solution {
public int coinChange(int[] coins, int amount) {
int length = coins.length;
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 3);
dp[0] = 0;
for (int i = 1; i <= amount; i++) {
for (int j = 0; j < length; j++) {
if (i - coins[j] >= 0 ) {
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[amount] == amount + 3 ? -1 : dp[amount];
}
}
写法1:外层遍历coins,内层遍历amount
class Solution {
public int coinChange(int[] coins, int amount) {
int length = coins.length;
int[] dp = new int[amount + 1];
Arrays.fill(dp, amount + 3);
dp[0] = 0;
for (int i = 0; i < length; i++) {
for (int j = 1; j <= amount; j++) {
if (j - coins[i] >= 0 ) {
dp[j] = Math.min(dp[j], dp[j - coins[i]] + 1);
}
}
}
return dp[amount] == amount + 3 ? -1 : dp[amount];
}
}