Python兑换零钱

引言

在现实生活中,我们经常会遇到需要兑换零钱的情况,比如去超市购物后需要找零钱。而对于商家来说,通常会尽量使用较少数量的硬币/纸币来找零,以便降低找零的成本。在这种情况下,我们可以使用Python来解决这个问题。

本文将介绍一个使用动态规划算法解决兑换零钱问题的Python代码示例,并使用序列图来说明算法的执行过程。

动态规划算法

动态规划算法是一种通过拆分问题为更小的子问题,并通过子问题的解来解决原问题的方法。对于兑换零钱的问题,我们可以将其拆解为一个个子问题,每个子问题表示兑换一定金额的零钱所需的最少硬币数量。

假设我们有一组硬币面额为 [1, 2, 5],需要兑换金额为 11 的零钱。我们可以定义一个长度为 12 的列表 dp,其中 dp[i] 表示兑换金额为 i 的零钱所需的最少硬币数量。初始时,我们将列表中的所有元素设为一个较大的数,以便后续比较取最小值。

代码示例

下面是使用动态规划算法解决兑换零钱问题的Python代码示例:

def coinChange(coins, amount):
    # 初始化dp列表
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0

    for i in range(1, amount + 1):
        for coin in coins:
            if i - coin >= 0:
                dp[i] = min(dp[i], dp[i - coin] + 1)

    if dp[amount] == float('inf'):
        return -1
    else:
        return dp[amount]
        
coins = [1, 2, 5]
amount = 11
print(coinChange(coins, amount))

在上述代码中,我们首先定义了一个 coinChange 函数,它接受两个参数:coinsamountcoins 是一个整数列表,表示可用的硬币面额,amount 是需要兑换的金额。

函数开始时,我们初始化一个长度为 amount + 1dp 列表,将其中的所有元素设为一个较大的数(这里使用 float('inf') 表示正无穷大)。然后,我们将 dp[0] 初始化为 0,表示兑换金额为 0 的零钱所需的最少硬币数量为 0

接下来,我们使用两层循环遍历所有金额(从 1amount)和可用的硬币面额。对于每个金额 i,我们尝试使用每个硬币面额 coin 进行兑换,并更新 dp[i] 的值为 dp[i - coin] + 1 的最小值。

最后,我们检查 dp[amount] 的值是否为正无穷大。如果是,则表示无法兑换金额为 amount 的零钱;如果不是,则返回 dp[amount],即兑换金额为 amount 的零钱所需的最少硬币数量。

在上述代码的最后,我们使用了一个例子来演示函数的使用,将 coins 设置为 [1, 2, 5]amount 设置为 11,并打印出结果。

序列图

下面是使用mermaid语法绘制的序列图,说明了动态规划算法在兑换零钱问题中的执行过程:

sequenceDiagram
    participant User
    participant Program

    User->>Program: 提供硬币面额和兑换金额
    Program->>Program: 初始化dp列表
    Program->>Program: 设定初始值
    Program->>Program: 开始动态规划
    Program->>Program: 更新dp列表
    Program->>Program: 返回兑换