📅  最后修改于: 2023-12-03 15:10:44.671000             🧑  作者: Mango
这是一个经典的面试题,在实际生活中也有很多应用场景,比如找零、货币兑换等。要求编写一个函数,输入一个总金额和一组纸币面额,输出最小数量的纸币和值,使其等于总金额。如果无法组成总金额,则返回 -1。
该问题可以采用动态规划求解,具体思路如下:
定义状态:我们用 dp[i] 表示凑出金额 i 的最小数量,那么最终结果就是 dp[amount],其中 amount 是给定的总金额。
初始化:将 dp 数组全部初始化为无穷大,但 dp[0] = 0。因为凑出金额为 0 需要 0 张纸币。
状态转移:对于每种面额的纸币,我们可以选择使用或者不使用,因此状态转移方程为:
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
其中 coins[j] 表示第 j 种纸币面额,i - coins[j] 表示在不使用当前面额的情况下,凑出剩余金额的最小数量,然后加上当前面额的一张纸币,就可以得到凑出金额 i 的最小数量。
返回值:如果最终的答案为无穷大,则说明无法组成总金额,返回 -1。
下面是使用 Python 语言实现的代码:
def coinChange(coins, amount):
dp = [float('inf')] * (amount + 1)
dp[0] = 0
for i in range(1, amount + 1):
for j in range(len(coins)):
if i - coins[j] >= 0:
dp[i] = min(dp[i], dp[i - coins[j]] + 1)
return dp[amount] if dp[amount] != float('inf') else -1
该函数的时间复杂度为 $O(nm)$,其中 n 是总金额,m 是纸币的种类数。空间复杂度为 $O(n)$。