322. 零钱兑换
Origin: LeetCode 322
题目描述
给定不同面额的硬币 coins 和一个总金额 amount,计算凑成总金额所需的最少硬币个数。如果无法凑出,返回 -1。每种硬币可无限次使用。
示例
Input: coins = [1, 2, 5], amount = 11
Output: 3
Explanation: 11 = 5 + 5 + 1
Input: coins = [2], amount = 3
Output: -1
Input: coins = [1], amount = 0
Output: 0
约束
- 1 <= coins.length <= 12
- 1 <= coins[i] <= 2^31 - 1
- 0 <= amount <= 10
关键信息
- 完全背包,硬币无限次使用
- dp[i] = min(dp[i], dp[i - coin] + 1)
- 和 HackerRank 第 37 题、LeetCode 第 279 题完全一样的框架
- 凑不出返回 -1(Infinity 判断)
Resolution
我的解法
function coinChange(coins: number[], amount: number): number {
// dp[i] = min(dp[i], dp[i - coin] + 1)
const dp = Array.from({ length: amount + 1 }, () => Infinity)
dp[0] = 0
for (let i = 1; i <= amount; i++) {
let min = dp[i]
for (const coin of coins) {
if (i >= coin) {
min = Math.min(min, dp[i - coin] + 1)
}
}
dp[i] = min
}
return dp[amount] === Infinity ? -1 : dp[amount]
}解题思路
完全背包 / 硬币找零。和 HackerRank 第 37 题、LeetCode 第 279 题完全一样的框架。
- dp[i] = 凑齐金额 i 所需的最少硬币数
- dp[0] = 0,其他初始化 Infinity
- 对每个金额 i,遍历所有硬币,dp[i] = min(dp[i], dp[i - coin] + 1)
- i >= coin 防越界,最后 Infinity 返回 -1
复杂度
- 时间:O(n × m),n 是 amount,m 是 coins 长度
- 空间:O(n)