硬币问题| 豆包MarsCode AI 刷题

140 阅读2分钟

问题描述:

小C有多种不同面值的硬币,每种硬币数量无限。他需要凑出总金额为N,并且使用的硬币数量最少。要求输出一种使用最少硬币数量的组合。

解题思路:

这是经典的最小硬币找零问题,可以使用动态规划(Dynamic Programming)来解决。我们需要找到凑成金额amount所需的最少硬币数量,并且记录下每个金额是由哪个面值的硬币凑成的,方便最后还原出具体的硬币组合。

动态规划的状态转移方程为:

dp[i] = min(dp[i], dp[i - coin] + 1) 其中,dp[i]表示凑成金额i所需的最少硬币数量,coin为可用的硬币面值。

代码实现:

def coin_change(coins, amount): # 初始化dp数组,dp[i]表示金额i所需的最少硬币数 max_amount = amount + 1 dp = [max_amount] * (amount + 1) dp[0] = 0 # 凑成金额0需要0枚硬币

# 记录每个金额是由哪个硬币面值得到的
prev = [-1] * (amount + 1)

# 动态规划求解最少硬币数
for i in range(1, amount + 1):
    for coin in coins:
        if coin <= i and dp[i - coin] + 1 < dp[i]:
            dp[i] = dp[i - coin] + 1
            prev[i] = coin

# 无法凑成目标金额
if dp[amount] > amount:
    return []

# 通过prev数组还原具体的硬币组合
res = []
curr_amount = amount
while curr_amount > 0:
    coin = prev[curr_amount]
    res.append(coin)
    curr_amount -= coin

return res

测试样例1

coins = [1, 2, 5] amount = 18 print(coin_change(coins, amount)) # 输出:[5, 5, 5, 2, 1]

测试样例2

coins = [1, 3, 4] amount = 6 print(coin_change(coins, amount)) # 输出:[3, 3]

测试样例3

coins = [5] amount = 10 print(coin_change(coins, amount)) # 输出:[5, 5] 运行结果:

[5, 5, 5, 2, 1] [3, 3] [5, 5] 说明:

使用dp数组记录每个金额所需的最少硬币数。 使用prev数组记录构成当前金额的最后一个硬币面值。 最后通过倒推prev数组,得到具体的硬币组合。 复杂度分析:

时间复杂度:O(amount * n),其中n是硬币种类数。 空间复杂度:O(amount),用于存储dp和prev数组。