法1:动态规划
看了题解
想法:
- 总金额amount是背包容量
- coins是物品(coins.length是物品种类;coins[i]为每种物品的体积)
- 每种物品有无限个
- 目标:用最少数量的物品把背包填满
/**
* @param {number[]} coins
* @param {number} amount
* @return {number}
*/
var coinChange = function(coins, amount) {
// amount是背包容量
// coins是物品(coins.length是物品种类;coins[i]为每种物品的体积)
// 每种物品有无限个
if(amount == 0) {
return 0;
}
var dp = [], i = 0, j = 0;
for(j = 0; j <= amount; j++) {
dp[j] = 0;
}
for(j = 0; j < coins.length; j++) { // 遍历每一个硬币
// 对每一个硬币,遍历可以装下它的背包
// 硬币不限数量:从小包往大包遍历,可以实现同一面额的硬币的多次加入
for(i = coins[j]; i <= amount; i++) {
if(i == coins[j]) {
// 正好可以装下
dp[i] = 1;
}
else if(dp[i] == 0 && dp[i - coins[j]] != 0) {
// 容量为i的背包:第一次试着装入
dp[i] = dp[i - coins[j]] + 1;
}
else if(dp[i - coins[j]] != 0) {
// 容量为i的背包:已经装入过,比较两种装入方式,哪种硬币数量更少
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
if(dp[amount] == 0) {
return -1;
}
else {
return dp[amount];
}
};