返回

LeetCode 322. Coin Change(Python):深入理解动态规划和备忘录

后端

  1. LeetCode 322. Coin Change 题意简介

LeetCode 322. Coin Change(Python)是LeetCode题库中一道经典的动态规划问题。题目如下:

给定一种硬币,它的面额为c1,c2,...,cn,你需要用这些硬币凑出金额为amount的零钱。求出凑出这个金额的硬币组合数的最小值。如果 невозможно凑出金额amount,则返回-1。

比如,给定硬币的面额为[1,2,5]和amount=11,则可以凑出金额11的硬币组合为[5,5,1]和[2,2,2,2,2,1]。最小组合数为2,所以返回2。

2. 动态规划算法的应用

本题的求解可以使用动态规划算法。动态规划算法是一种自底向上的求解方法,它将问题的解空间划分为若干个子问题,然后逐个求解这些子问题,最终得到整个问题的解。

对于本题,我们可以定义一个二维数组dp,其中dp[i][j]表示使用前i个硬币凑出金额j所需的最小硬币数量。显然,dp[i][j]可以由dp[i-1][j]和dp[i][j-c_i]转移而来,即:

dp[i][j] = min(dp[i-1][j], dp[i][j-c_i] + 1)

其中,c_i表示第i个硬币的面额。

3. 备忘录的应用

为了避免重复计算,我们可以使用备忘录来记录已经计算过的子问题的解。这样,当我们再次遇到相同的子问题时,可以直接从备忘录中取出结果,而无需重新计算。

在LeetCode 322. Coin Change(Python)中,我们可以使用一个字典作为备忘录。字典的键是子问题的状态,即(i, j),字典的值是子问题的解,即dp[i][j]。

4. 算法实现

接下来,我们给出本题的Python代码实现:

def coin_change(coins, amount):
  """
  :type coins: List[int]
  :type amount: int
  :rtype: int
  """

  # 初始化备忘录
  memo = {}

  def dp(i, j):
    """
    :type i: int
    :type j: int
    :rtype: int
    """

    # 已经计算过子问题的解,直接从备忘录中取出
    if (i, j) in memo:
      return memo[(i, j)]

    # 递归终止条件
    if j == 0:
      return 0

    # 超出硬币数组的范围
    if i < 0:
      return -1

    # 硬币面额大于剩余金额
    if coins[i] > j:
      return dp(i - 1, j)

    # 当前硬币面额小于剩余金额
    # 可以选择使用当前硬币或者不使用当前硬币
    result = min(dp(i - 1, j), dp(i, j - coins[i]) + 1)

    # 将子问题的解放入备忘录
    memo[(i, j)] = result

    return result

  # 调用函数计算最终结果
  result = dp(len(coins) - 1, amount)

  # 不存在解
  if result == -1:
    return -1

  # 返回最少的硬币数量
  return result

5. 时间复杂度分析

使用动态规划和备忘录求解LeetCode 322. Coin Change(Python)的时间复杂度为O(n*amount),其中n是硬币的数量,amount是目标金额。

6. 练习题

为了巩固所学知识,您可以尝试以下练习题:

  1. 给定一种硬币,它的面额为c1,c2,...,cn,你需要用这些硬币凑出金额为amount的零钱。求出凑出这个金额的硬币组合数的最大值。如果 невозможно凑出金额amount,则返回-1。
  2. 给定一种硬币,它的面额为c1,c2,...,cn,你需要用这些硬币凑出金额为amount的零钱。求出凑出这个金额的硬币组合数的所有可能情况。
  3. 给定一种硬币,它的面额为c1,c2,...,cn,你需要用这些硬币凑出金额为amount的零钱。求出凑出这个金额的硬币组合数的所有可能情况,并且每种组合中硬币的个数不超过k个。

7. 总结

LeetCode 322. Coin Change(Python)是一道经典的动态规划问题,通过这道题,我们深入理解了动态规划算法的思想和备忘录的应用。此外,我们还提供了多种练习题,帮助您巩固所学知识。希望本文能够对您的学习有所帮助。