这是我参与11月更文挑战的第20天,活动详情查看:2021最后一次更文挑战
换钱的最少货币数
问题描述
322. 零钱兑换
给定数组arr,arr中所有的值都为正整数且不重复。每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个aim,代表要找的钱数,求组成aim的最少货币数。如果无解,请返回-1.
示例:
输入:coins = [1, 2, 5],amount = 11
输出:3
说明:11 = 5 + 5 + 1
分析问题
由于题目是求最优解问题,所以我们最直观的感觉就是这题是否可以使用动态规划来求解。
我们都知道,对于求解动态规划相关的问题,最重要的就是求出状态转移方程。下面我们来看一下如何求解,首先我们定义F(S) 为组成金额 S 所需的最少货币数量。
假设目前我们已经知道了F(S),和最后一枚货币的面值是C,我们就可以得出:
F(S)=F(S-C)+1
由于最后一枚货币的面值是未知的,所以我们需要枚举每个货币的面额值 C0, C1,…..,Cn-1,并选择其中的最小值。即
F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),….,F(S-Cn-1)} + 1
S-Ci >=0
当S=0时,F(S)=0
当n=0时,即货币的种类为0时,F(S)无解,即F(S)=-1
所以,F(S)的状态转移方程为
F(S)=min {F(S-C0) ,F(S-C1),F(S-C3),….,F(S-Cn-1)} + 1
其中 Cj 代表的是第 j 枚货币的面值,即我们枚举最后一枚货币面额是Cj,那么F(S)需要从S-Cj这个金额对应的状态 F(S-Cj) 转移过来,再加上枚举的这枚货币数量1的贡献。由于题目是求货币的数量最少,所以 F(S)为前面能转移过来的状态的最小值。
假设 coins= [1, 2, 5],amount = 11,即F(11) = min( F(10), F(9), F(6) ) + 1。
下面我们来看一下代码的实现。
1 | ini复制代码import sys |
该算法的时间复杂度是O(Sn),其中S是金额数,n是不同面额的个数。空间复杂度是O(S)。
本文转载自: 掘金