题目链接
https://leetcode.com/problems/coin-change/
题目描述
给定不同面值的硬币和一个金额,计算组成这个金额最少需要的硬币数量并返回。如果任意硬币组合都无法达到给定的数额则返回-1。
示例
输入:coins = [1,2,5],amount = 11
输出:3
(11 = 5 + 5 + 1)
输入:coins = [1],amount = 2
输出:2
解决思路一
零钱兑换问题相当于是爬楼梯的变种:11级的台阶,每次只能迈1、2、5级,最少可以迈多少次?
同时如果将amount视为背包容量,coins中硬币的面值视为商品重量,每种商品可以使用无限次,因此也可以将零钱兑换问题理解为完全背包问题:
这个优化题目可以由动态规划来解决,因为组合给定金额的最优解问题可以由组合更小数额的最优解组合而成。
动态规划有两种等价的实现方法:一是带备忘的自顶向下法;另一个是自底向上法。带备忘的自顶向下法需要按照自然的递归形式编写过程,但是过程会保存每个子问题的解,需要一个子问题的解时,过程首先会检查是否已保存过这个解。如果已经保存过则直接返回保存的值,否则按通常方式计算这个子问题。自底向上法需要将子问题按照从小到大的规模排序并依次求解。当求解某个子问题时,它所依赖的更小的子问题已经计算完毕并保存。每个子问题只需求解一次,当我们求解一个子问题时,它所依赖的子问题都已经求解完毕。
首先用带备忘的自顶向下法来实现:定义F(S)表示组成金额S所需要的最少硬币数量,那么进一步可以将这个问题的规模减小:
C为组成F(S)的最后一枚硬币ÿ