let coins = [1, 2, 5, 10]
function coinChange(coins, subMoney) {
// 创建一个dp数组,里面的值为无穷大
let dp = new Array(subMoney+1).fill(Infinity);
// 交换0元时需要0枚硬币
dp[0] = 0
// i为要交换的金额
for (let i = 1; i <= subMoney; i++) {
// j为可使用硬币的下标
for (let j = 0; j < coins.length; j++) {
// 要交换的硬币的金额减去使用了的硬币
let temp = i - coins[j]
// 如果temp>=0就证明可以使用硬币来交换,若小于0就证明没有硬币可以来交换如交换 -1元
if(temp >= 0) {
// 递推函数为 f(i) = min(f(i-coins[0]),f(i-coins[1]),f(i-coins[2]),...f(i-coins[n])) + 1
// 递推函数的意思为:最小硬币枚数就是 上一次硬币枚数加上这个金额的一枚硬币 就是总枚数
// 因此下面的函数的意思为两两取最小,直到取到最小
dp[i] = Math.min(dp[temp], dp[i]) + 1
}
}
}
// maxChangeMoney是当前要交换的钱
let maxChangeMoney = subMoney // 刚开始要交换的钱是subMoney
for (let i = dp.length; i >0; i--) {
// 当dp数组里有比当前硬币数量小的就证明 上一次的钱加上了一枚硬币之后足够交换了
// 加上的硬币的面额为总面额减去硬币数量少的那个面额就是使用的硬币面额
// 然后待交换硬币的金额maxChangeMoney就是原来的减去硬币的面额
if(dp[i] < dp[maxChangeMoney]){
console.log(`使用了面值为${maxChangeMoney - i}的硬币交换`);
// 当硬币交换的数量为1时,就证明这枚硬币就是最后的硬币,直接结束循环
if (dp[maxChangeMoney]===1){
console.log(maxChangeMoney,"---------------");
console.log(`使用了面值为${maxChangeMoney}的硬币交换`);
break
}
maxChangeMoney = i
}
}
return dp[subMoney] //输出的就是交换硬币的最小数量
}
coinChange(coins, 15)
最少硬币交换问题 ---动态规划
最新推荐文章于 2022-02-01 10:46:08 发布