当前位置: 首页 > 知识库问答 >
问题:

如何使用递归输出最小变化问题中的实际硬币组合

黄君博
2023-03-14

给定一个硬币面额列表和一个目标值,我正在尝试创建一个递归函数,它将告诉我生成该值所需的最小硬币数量,然后显示我需要哪些硬币。例如,输入硬币[1,5,10,25],目标为6,输出应该是“你需要2枚硬币:[1,5]”。我写了一个函数,告诉我需要多少硬币,但我也想看看硬币的组合是什么。

# USD - $1, $5, $10, etc.
currency = [1, 5, 10, 20, 50, 100]

# the amount to change - eg $6
amount = 6

cache = dict() 

def recursive_change(currency, amount):
  if amount in cache.keys() is not None:
    return cache[amount]

  # base case
  if amount == 0:
    return 0

  result = amount+1 # initially result is just some high number 
  #I figure amount + 1 is fine because we'd never use more coins than the value (assuming we can't have coins worth less than one)

  for coin in currency:
    if coin <= amount:
      result = min(result, recursive_change(currency, amount-coin) + 1)
  cache[amount]=result
  return result

这是我刚刚制作的另一个版本-我注意到我的初始解决方案不能很好地处理不可能的输入(例如,只使用五分镍币和一角镍币赚6美分),所以现在它返回-1表示不可能的数量。虽然有点难看,但我希望能为它做得更好一些。

def recursive_change(currency, amount):
  if amount in cache.keys():
    return cache[amount]

  # base case
  if amount == 0:
    return 0

  # If we can't make the amount with this coin, return -1
  if amount < 0:
    return -1

  result = -1

  for coin in currency:
    if coin <= amount:
      current_result = recursive_change(currency, amount-coin) 
      if current_result >= 0: 
        if result < 0:
          result = current_result 
        else: 
          result = min(current_result, result) 

  if result < 0:
    result = -1
  else:
    result = result + 1
  cache[amount]=result
  print(cache)
  return result

共有2个答案

柳羽
2023-03-14

该解决方案使用递归找到贪婪算法失败的理想解决方案,使用缓存,因此它应该与DP迭代方法一样快,并输出实际的硬币组合。

# currency denominations
currency = [2,3,15,25]

# the amount to make change for - eg $30
amount = 30

# cache contains the best currency combos for each value: eg cache[7]=[5,1,1]
cache = dict()
def recursive_change(currency, amount):
  if amount in cache.keys():
    return []+cache[amount] # Had to do this [] thing so it passes a copy

  # base case
  if amount == 0:
    return []

  # If we can't make the amount with this coin, return -1
  if amount < 0:
    return [-1]

  best_combo = [-1]

  for coin in currency:
    current_result = recursive_change(currency, amount-coin)
    if current_result == [] or current_result[0] >= 0: 
      current_result.append(coin)  # if we picked a coin, we add it to the list
      if best_combo[0] < 0:
        best_combo = current_result 
        # if we found the first coin combo that works for the current problem, set best so we don't compare to -1 below
      else: 
        # if this isn't the first coin combo that works for the current problem, check to see if it's better than any of the other coin combos
        if len(current_result) < len(best_combo):
          best_combo = current_result

  cache[amount]=[]+best_combo # Had to do this [] thing so it passes a copy
  return best_combo
谭向晨
2023-03-14

你的方法效率很低,尤其是对于大笔资金。你应该开始从最高面额产生总和,而不是从最低面额产生总和。以下是返回面额和硬币/钞票数量的更快更简单的版本:

currency = [1, 5, 10, 20, 50, 100]

def recursive_change(currency, amount):
    for c in reversed(currency) :
        if amount >= c :
            return [(amount // c, c),] + recursive_change( currency, amount % c )
    return []

recursive_change( currency, 6 )
>>> [(1, 5), (1, 1)]

这意味着一枚5硬币和一枚1硬币。

还有几个测试结果:

>>> recursive_change( currency, 77 )
[(1, 50), (1, 20), (1, 5), (2, 1)]
>>> recursive_change( currency, 99 )
[(1, 50), (2, 20), (1, 5), (4, 1)]
 类似资料:
  • 给定一个值N,如果我们想改变为N美分,并且我们有无限量的S={S1,S2,...,Sm}值的硬币,我们有多少种方法可以改变?硬币的顺序并不重要。不过还有一个额外的限制:你只能用正好是K的硬币换零钱。 例如,对于N=4,k=2和S={1,2,3},有两个解:{2,2},{1,3}。所以输出应该是2。 解决方案: 以上是递归解决方案。但是,我需要有关动态规划解决方案的帮助: 让表示与元素和硬币的总和。

  • 我试图用递归来解决硬币兑换问题,遇到了下面的代码。 问题:给定一些面额的无限硬币,计算它们形成给定数量的方式。 输入: 代码: 我理解代码本身,也理解基本情况,但是我不理解它是如何封装递归/解决方案的。 例如,如果我正在求解,我可以说,因此我可以清楚地“看到”递归。在换硬币的例子中,我无法推断出类似的关系。有人能帮我吗?

  • 这个问题和这里问的一样。 给定一个硬币列表,它们的值(c1,c2,c3,... cj,...),以及总和i。找出硬币总数为i的最小数量(我们可以根据需要使用一种类型的硬币),或者报告不可能以总和为S的方式选择硬币。 我昨天刚刚被介绍到动态编程,我试图为它编写一个代码。 这里,C[i]是货币量“i”的最优解。可用的硬币有{c1,c2,…,cj,…}对于这个程序,我增加了递归限制,以避免最大递归深度超

  • 我需要编写一个算法,它接收一个数字和一个数字列表,并从列表中返回可能的数字组合的数量,从而可以创建和数。例如:def coin(5,[1,2,5,6]应该返回数字4,因为列表中有4种可能的组合可以一起创建数字5。下面是我尝试过的代码,但它不起作用。输出是6而不是4,我希望您能帮助我理解为什么。

  • 给定一组硬币面额和一个,找出所有可能的组合,使硬币总数达到最小。在我的解决方案中,我在中记录了总计为的最小硬币数。我不确定这将如何修改以存储总计为的实际硬币,并确保在这种情况下包括这两种可能性。我看过其他关于堆栈溢出的代码,但我只找到可以打印任何一个最佳解决方案的代码。 输入:最小硬币(10,[2,3,5,6,7,8]) 输出:[[5,5],[2,8]]

  • 具体而言,问题是: 给定面额数组<代码>硬币[],每个硬币的限制数组<代码>限制[]和数量<代码>金额,返回所需的最小硬币数量,以获取<代码>金额,或者如果不可能,返回空值。另外,用溶液中使用的每个硬币的数量填充数组 这是我的解决方案: 但它一般不起作用。 我的问题是,例如,在这种情况下: 最佳解决方案是: 并且我的算法给出作为结果。换句话说,它失败了,每当在某种情况下,我将不得不使用比可能的更少