322. [✔][M]零钱兑换
给你一个整数数组 coins
,表示不同面额的硬币;以及一个整数 amount
,表示总金额。
计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额,返回 -1
。
你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
示例 2:
输入:coins = [2], amount = 3
输出:-1
示例 3:
输入:coins = [1], amount = 0
输出:0
提示:
1 <= coins.length <= 12
1 <= coins[i] <= 231 - 1
0 <= amount <= 104
题解:
// @lc code=start
function coinChange(coins: number[], amount: number): number {
// 自底向上
// dp[i]表示总金额为i的话最少需要几个硬币
let dp = new Array(amount + 1).fill(amount + 1);
// base条件
dp[0] = 0;
for (let i = 0; i < dp.length; i++) {
for (const coin of coins) {
if (i < coin) {//相当于需要的金额比这个硬币还小
continue;
}
dp[i] = Math.min(dp[i], 1 + dp[i - coin]);
}
}
return (dp[amount] === amount + 1) ? -1 : dp[amount];
// // 自顶向下
// let memo = new Array(amount + 1).fill(-999);
// const dp = (coins: number[], total: number): number => {
// // base条件
// if (total === 0) {
// return 0
// }
// if (total < 0) {
// return -1;
// }
// // 备忘录
// if (memo[total] !== -999) {
// return memo[total];
// }
// let res = Number.MAX_SAFE_INTEGER;
// // 做选择,计算子问题
// for (const coin of coins) {
// let subProblem = dp(coins, total - coin);
// if (subProblem === -1) {
// continue;
// }
// res = Math.min(res, subProblem + 1);
// }
// // 存入备忘录
// memo[total] = (res === Number.MAX_SAFE_INTEGER) ? -1 : res
// return memo[total];
// }
// return dp(coins, amount);
};
// @lc code=end