322. 零钱兑换
思路
1. dp数组的含义
dp[j]: 凑足金额为j所需要的最少硬币为dp[j]个。
2. 确定递推公式
对于遍历到的硬币coin[i],它可以和金额和为j-coin[i]的硬币们凑成金额j,那么所需的最少个数就是dp[j-coin[i]]+1(加上它自己),如果这个值小于不考虑coin[i]时的值dp[j],就选择它,否则选择原来的值。
3. 初始化
凑足0元所需最少的硬币肯定是0个——不选就行了,所以dp[0] = 0。对于下标为非零的dp值应该是无穷大,这样才能被选择最小的值时被覆盖。
4. 遍历顺序
这里考虑的是装满背包的个数问题,和遍历硬币的顺序无关,可以外层遍历背包容量(即金额),内层遍历物体(即硬币),也可以交换。
5. 举例推导dp数组
以输入:coins = [1, 2, 5], amount = 5为例,
dp[0] = 0, dp[1] = 1, dp[2] = 1, dp[3] = 2, dp[4] = 2, dp[5] = 1
代码实现
class Solution(object):
def coinChange(self, coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for coin in coins:
for i in range(coin, amount + 1):
dp[i] = min(dp[i - coin] + 1, dp[i])
return dp[amount] if dp[amount] != float('inf') else -1