📌  相关文章
📜  硬币变化 - 硬币的最小数量 (1)

📅  最后修改于: 2023-12-03 15:41:02.417000             🧑  作者: Mango

硬币变化 - 硬币的最小数量

介绍

在计算机程序中,我们经常会涉及到货币的问题。例如,我们需要给一组钱数找零时,如何使用最少的硬币数来实现找零,就是一个典型的问题。

硬币变化问题即为:给定不同面额的硬币和总金额,找出可以凑成总金额所需的最少的硬币数。例如,当硬币面值为[1, 2, 5],总金额为11时,最少需要的硬币数为3(即1个面额为5的硬币,1个面额为2的硬币,3个面额为1的硬币)。

解决方案

硬币变化问题可以使用贪心算法来解决,也可以使用动态规划算法来解决。

贪心算法

贪心算法即为每次都选择最优解的算法。在硬币变化问题中,我们可以每次都选择面值最大的硬币尽可能的凑齐总金额,然后再选择次大的硬币,以此类推。通过贪心算法,我们可以得到一组有效的解,但并不一定是最优解。

例如,当硬币面值为[1, 2, 5],总金额为11时,贪心算法会选择1个面额为5的硬币、3个面额为2的硬币,共计4枚硬币。此时还有更优解:2个面额为5的硬币、1个面额为1的硬币,共计3枚硬币。

动态规划算法

动态规划算法则是通过将问题拆成多个子问题,每个子问题只解决一次,并将解缓存下来,以便后续复用,最终得到总问题的解。在硬币变化问题中,我们可以定义一个数组dp,dp[i]表示凑齐面值为i的总金额所需要的最少硬币数。则dp[i]的值可以由dp[i-coins[j]]与1的最小值加1组成,其中coins[j]表示硬币面值的数组,即:

dp[i] = min(dp[i-coins[j]]) + 1,其中i ≥ coins[j],0 ≤ j < coins的长度。

例如,当硬币面值为[1, 2, 5],总金额为11时,动态规划算法会选择2个面额为5的硬币、1个面额为1的硬币,共计3枚硬币。

代码实现

以下是python代码实现硬币变化问题的最少硬币数的功能,分别使用了贪心算法和动态规划算法解决:

def coinChangeGreedy(coins, amount):
    coins.sort(reverse=True)  # 从大到小排列硬币面值
    count = 0
    for coin in coins:
        if amount == 0:
            return count
        if amount < coin:
            continue
        count += amount // coin
        amount = amount % coin
    return count if amount == 0 else -1


def coinChangeDP(coins, amount):
    if amount < 1:
        return 0
    dp = [float('inf')] * (amount + 1)
    dp[0] = 0
    for i in range(1, amount + 1):
        for coin in coins:
            if i >= coin:
                dp[i] = min(dp[i], dp[i - coin] + 1)
    return dp[amount] if dp[amount] != float('inf') else -1

以上是列举的硬币变化 - 硬币的最小数量问题的解决方式及代码示例,希望能对大家的理解和使用有所帮助。