零钱兑换问题简介:
零钱兑换问题是一个经典的动态规划问题,题目的核心是给定不同面额的硬币以及一个总金额,要求计算出组成总金额所需的最少硬币数量。
解决方案:
-
动态规划(Dynamic Programming)方法:
- 使用一个数组
dp存储每个金额所需的最少硬币数量。 - 从金额为 0 开始到目标金额,逐步计算最少硬币数量。
- 对于每个金额,遍历所有硬币面额,更新
dp数组中的最小值。 - 最终
dp[amount]即为所需的最少硬币数量。
- 使用一个数组
-
递归回溯方法:
- 通过递归进行深度优先搜索,尝试每种硬币组合来达到目标金额。
- 对于每个硬币面额,逐个尝试,直到找到最优解。
- 递归方法的缺点是可能会遍历大量相同的组合,效率较低。
思考要点:
- 处理边界条件:如目标金额为 0,或者没有硬币时的特殊情况。
- 动态规划中的状态转移方程:确定状态转移方程是解决动态规划问题的关键。
解决方案之递归
通过递归,可以进行深度优先搜索,尝试不同的硬币组合,以确定达到目标金额所需的最少硬币数量。
- 示例:
function coinChange(coins, amount) {
// 递归函数,传入当前金额
function helper(t) {
// 递归结束条件
if (t === 0) return 0;
if (t < 0) return -1;
let minCoins = Infinity;//使minCoins为最大值
// 遍历每个硬币面额
for (let coin of coins) {
const res = helper(t - coin);
if (res >= 0 && res < minCoins) {
minCoins = res + 1;
}
}
return minCoins !== Infinity ? minCoins : -1;
}
return helper(amount);
}
const coins = [1, 2, 5]; // 不同面额的硬币
const amount = 11; // 总金额
const result = coinChange(coins, amount);
console.log("最少硬币数量为:", result);
- 以上代码中,使用
coinChange函数接受coins(不同面额的硬币)和amount(总金额)作为输入参数。 - 设置一个
helper递归函数,它接受当前需要凑成的金额t。 - 在
helper函数中,首先判断递归结束条件:当目标金额t等于 0 时,返回硬币数量为 0;当目标金额小于 0 时,返回 -1,表示无法解决。 - 对于每个硬币面额,递归调用
helper(t - coin)来求解剩余金额所需的最少硬币数量。 - 在递归过程中,不断更新最小硬币数量
minCoins,直到找到最优解。 - 返回最小硬币数量,如果无法凑成目标金额则返回 -1。
解决方案之动态规划
使用动态规划方法来解决零钱兑换问题,通过计算最小的硬币数量来凑成目标金额。动态规划的思想是从底向上逐步计算金额为 i 时的最少硬币数量,直至达到目标金额。
- 示例
const coinChange = function (coins, amount) {
const f = [];
f[0] = 0;
for (let i = 1; i <= amount; i++){
f[i] = Infinity;//先设置为最大值
for (let j = 0; j < coins.length; j++){
if (i - coins[j] >= 0) {
f[i] = Math.min(f[i], f[i - coins[j]] + 1);//取最小值 1表示当前硬币
//coins[j] 1个 f[i - coins[j]]表示剩余的钱数需要的最少硬币数
}
}
}
if (f[amount] === Infinity) {
return -1;
}
return f[amount];
}
console.log(coinChange([1, 2, 5], 11));
- 上述代码中,使用
coinChange函数接受coins(不同面额的硬币)和amount(总金额)作为输入参数。 - 创建了一个
f数组用于接收最少硬币数量 - 将
f[0](金额为 0 时)设为 0,因为凑成金额为 0 时,不需要硬币。 - 使用两层循环进行动态规划的状态转移计算。外层循环遍历金额
i,内层循环遍历每个硬币的面额coin。 - 在每次计算时,判断当前金额
i是否大于等于当前硬币面额coin。如果是,则更新f[i]为f[i - coin] + 1和当前f[i]的最小值,表示凑齐金额i所需的最少硬币数量。 - 返回
f[amount],即为凑成目标金额所需的最少硬币数量,如果无法凑成则返回-1。