动态规划
解题思路
用dp[amount]来记录当前凑成amount最少需要的硬币数量
那么就可以得到一个状态转移方程
用当前这枚硬币(面值为 coin),加上凑出 i - coin 所需的最少硬币数。
dp[0] = 0 // 凑成 0 元需要 0 个硬币
dp[i] = Math.min(dp[i], dp[i-coin])
dp
var coinChange = function (coins, amount) {
let dp = new Array(amount + 1).fill(Infinity);
dp[0] = 0;
for (let i = 0; i <= amount; ++i) {
for (let coin of coins) {
if (i >= coin) {
dp[i] = Math.min(dp[i], dp[i - coin] + 1);
}
}
}
return dp[amount] === Infinity ? -1 : dp[amount];
};
dfs
- 定义函数
dfs(remain):表示凑出remain元需要的最少硬币数。 - 递归终止条件:
remain < 0:无法凑出,返回 -1remain === 0:正好凑出,返回 0memo[remain] !== -1:之前已经计算过,直接返回缓存结果
- 对每个硬币
coin,尝试递归调用dfs(remain - coin),并取最小值。 - 使用
memo[remain]缓存结果,避免重复计算。
var coinChange = function (coins, amount) {
let memo = new Array(amount + 1).fill(-1);
var dfs = function (remain) {
if (remain < 0) return -1;
if (remain === 0) return 0;
if (memo[remain] !== -1) return memo[remain];
let min = Infinity;
for (let coin of coins) {
const res = dfs(remain - coin);
if (res >= 0) {
min = Math.min(min, res + 1);
}
}
memo[remain] = min === Infinity ? -1 : min;
return memo[remain];
};
return dfs(amount);
};