题目描述
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 - 1。
思路:动态规划
第一步:明确[状态] 和 [选择]
- 状态是【背包的容量】也就是总金额 ,因为硬币数量不限制
- 选择是【放入背包】和【不放入背包】:做出什么样的选择改变当前状态(总金额减少)
** 第二步:明确 dp 数组的定义**
- dp[i] = x 表示 当目标金额为 i 时,至少需要 x 枚硬币。
- 初始化:
- dp[i] = amount + 1 (凑成amount金额最多需要amount个硬币(全是1元)),所以初始化为 amount + 1就相当于初始化为正无穷,便于后续取最小值。
- dp[0] = 0; (总金额为0 时不需要硬币)。
** 第三步:根据[选择],思考状态转移的逻辑**
- 无论当前目标金额是多少,选择就是从面额列表 coins 中选择一个硬币,然后目标金额就会减少。
- 选择需要 硬币数量 最少的那个结果
dp[i] = min(dp[i], dp[i - coin] + 1);
输出
- 最终返回 dp[amount];
注意:
- 首先硬币的面值要小于等于当前要凑出来的目标金额;
- 剩余的那个目标金额应该要能够凑出来
- 再强调一次:新状态的值要参考的是以前计算出来的【有效】状态值。
因此,不妨先假设凑不出来,因为比的是小,所以设置一个不可能的数。
代码
注意
- 要求的是【恰好】填满背包,所以初始化的时候需要赋值为一个不可能的值:amount + 1。
- 只有在【正常值】的时候,【状态转移】才可能发生。