返回
分解零钱花样多:LeetCode 518 零钱兑换 II 的组合计数
前端
2023-11-10 05:53:06
在日常生活中,我们经常会遇到找零钱的情况。当你用一张大面额的钞票购买小额商品时,收银员通常会找给你各种面额的硬币。那么,对于给定的面额和总金额,有多少种不同的找零方式呢?
这个问题正是 LeetCode 518 零钱兑换 II 中提出的问题。该问题要求我们编写一个函数,给定不同面额的硬币和一个总金额,计算有多少种方法可以凑成总金额。
为了解决这个问题,我们可以采用动态规划的方法。具体来说,我们可以定义一个二维数组 dp
,其中 dp[i][j]
表示使用前 i
种硬币凑成金额 j
的方法数。
def change(amount, coins):
"""
计算使用给定的硬币凑成总金额的方法数。
Args:
amount: 总金额。
coins: 硬币面额列表。
Returns:
凑成总金额的方法数。
"""
# 初始化 dp 数组。
dp = [[0] * (amount + 1) for _ in range(len(coins) + 1)]
# 初始化第一行和第一列。
dp[0][0] = 1
for j in range(1, amount + 1):
dp[0][j] = 0
# 填充 dp 数组。
for i in range(1, len(coins) + 1):
for j in range(1, amount + 1):
dp[i][j] = dp[i - 1][j]
if j >= coins[i - 1]:
dp[i][j] += dp[i][j - coins[i - 1]]
# 返回结果。
return dp[len(coins)][amount]
使用动态规划的方法,我们可以有效地计算出凑成总金额的方法数。该算法的时间复杂度为 O(amount * len(coins))
,其中 amount
是总金额,len(coins)
是硬币面额的个数。
为了加深理解,我们来看一个具体的例子。假设我们有面额为 1、2、5 的硬币,总金额为 10。那么,凑成 10 元的方法数为:
10 = 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1
10 = 1 + 1 + 1 + 1 + 1 + 1 + 2 + 2
10 = 1 + 1 + 1 + 1 + 1 + 5
10 = 1 + 1 + 1 + 2 + 5
10 = 1 + 1 + 2 + 2 + 2 + 2
10 = 1 + 2 + 2 + 5
10 = 2 + 2 + 2 + 2 + 2
10 = 5 + 5
因此,凑成 10 元的方法数为 8。
通过 LeetCode 518 零钱兑换 II 这道题,我们不仅学习了一种解决问题的动态规划方法,还锻炼了我们的逻辑思维能力。在实际生活中,我们也会经常遇到类似的问题,例如如何分配资源以实现最大收益。因此,这道题不仅在算法方面有意义,在现实生活中也有很强的实用价值。