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

Baktracking函数,用于计算超过最大递归深度的更改

袁法
2023-03-14

我试着写一个函数,找到所有可能的硬币组合,产生指定的金额,例如,它计算所有可能的方式,从面额1p,2p,5p,10p,20p,50p,1pound,2pound的列表中给2英镑的钱。我被这件事缠住了,找不到正确的解决办法。

我希望主函数是递归的,因为我想更好地理解递归。算法必须回溯,如果在某一时刻发现的组合超过了要匹配的数量,程序应该返回到以前的步骤,并从不同的点开始。

到目前为止,我已经编写了一个普通(不是递归)函数,如果每枚硬币只使用一次(这相当简单),该函数将计算给定国家所有可能的硬币组合。我并没有试图找到一个给定金额的正确组合,只是所有可能的硬币组合。

def calcCoins(coins):
    """ 
    returns all possible combinations of coins, when called with 
    [1,2,5,10,20,50,100,200] returns a list of 126 Counters containing 
    for instance Counter{1:1}, Counter{1:1,2:1,5:1}, Counter {50:1,100:1} etc
    """
    i,combs = 1, []
    while i < len(coins):
        for x in combinations(coins,i):
            combs.append(Counter(x))
        i += 1
    return combs

现在我有了一个笨拙的递归函数,它接受一个组合和所需的数量作为参数,并返回所有可能的方式,在这些方式中,可以给出等于这个数量的更改。

def findSum(comb,goal,rightOnes):
    if rightOnes == None:
        rightOnes = []
    if sum(comb.elements()) == goal:
        comb_ = Counter(comb)
        if comb_ in rightOnes:
             # probably a cycle, return combinations gathered and exit
             return rightOnes
        rightOnes.append(comb_)
    elif sum(comb.elements()) > goal:
        #this is meant to be backtracking
        return False
    for k in comb:
        comb[k] += 1
        if findSum(comb,goal,rightOnes) != False:
            return findSum(comb,goal,rightOnes)
        else:
            comb[k] = 1
    return rightOnes

对于非常小的组合,函数运行并正确返回:例如

test2 = Counter({10: 1, 20: 1})
findSum(test2,200,[])

它返回:

 [Counter({10: 18, 20: 1}), Counter({10: 16, 20: 2}), 
  Counter({10: 14, 20: 3}), Counter({10: 12, 20: 4}), 
  Counter({10: 10, 20: 5}), Counter({10: 8, 20: 6}), 
  Counter({20: 7, 10: 6}), Counter({20: 8, 10: 4}), 
  Counter({20: 9, 10: 2})]

但是对于更大的,比如

test3 = Counter({1: 1, 2: 1, 10: 1})
test4 = Counter({1: 1, 2: 1, 100: 1, 10: 1}) 

它超过了递归的极限。它运行正常,直到某个时刻,打印出部分结果,但在某个时候它超过了最大递归深度。

我犯了什么错误,导致这个函数失控?是因为我的回溯实现吗?我是不是漏掉了什么案子?如何优化这个函数,使其不超过最大递归深度?

提前谢谢!

编辑:以下是回溯:

   if findSum(comb,goal,rightOnes) != False:
   File "C:\playground\python\problem31.py", line 105, in findSum
   if sum(comb.elements()) == goal:
   File "C:\Python27\lib\collections.py", line 459, in elements
   return _chain.from_iterable(_starmap(_repeat, self.iteritems()))
   RuntimeError: maximum recursion depth exceeded while calling a Python object

最后一个部分结果,就在函数中断之前(用test3调用)

[Counter({1: 163, 2: 1, 20: 1, 10: 1, 5: 1}), Counter({1: 161, 2: 2, 20: 1, 10: 1, 5: 1}), 
 Counter({1: 159, 2: 3, 20: 1, 10: 1, 5: 1}), Counter({1: 157, 2: 4, 20: 1, 10: 1, 5: 1}), 
 Counter({1: 155, 2: 5, 20: 1, 10: 1, 5: 1}), Counter({1: 153, 2: 6, 20: 1, 10: 1, 5: 1})]

共有1个答案

路伟
2023-03-14

首先,正如这个问题的第一个答案所示,由于Python作为一种语言的语义,递归不是一种特别有效的范例。然而,正如上面所指出的,可以使用sys。设置递归限制(2000)。(或者不管你需要多少)我想强调这是一个“懒惰”的解决方案,我强烈建议使用你的第一个(非递归)版本。

 类似资料:
  • 我不明白为什么我会得到这个最大深度错误。iam试图使用bst递归方法在数组中查找数字索引,下面是我的代码 任何人都可以告诉我代码块中发生了什么 错误块: PS C:\Users\admin\Desktop\DSA

  • 问题内容: 我从星期一开始使用Python进行编程。我很喜欢学习它。但是我一直试图了解如何在tkinter菜单之间切换时避免递归!我确信这是一个非常基本的问题,感谢您宽容我对此主题的无知,但我无法在其他地方找到答案。 我现在正在做的最终是给我错误:RuntimeError:调用Python对象时超出了最大递归深度 这是我目前正在使用的模式。更新:下面的代码现在是完整的隔离副本,再现了我面临的问题!

  • 我对Python很陌生。我写了一个关于返回 x 在排序的重复元素数组 A 中的出现次数的函数: 错误是:运行时错误:超出最大递归深度。有人知道如何解决它吗?

  • 问题内容: 我使用以下代码解决了Euler项目的问题10,该代码通过强力工作: 这三个功能的工作方式如下: isPrime 检查数字是否为质数; primeList 返回一个列表,其中包含一组在一定范围内且限制为“ n”的素数,并且; sumPrimes 对列表中所有数字的值求和。(不需要最后一个功能,但是我喜欢它的清晰度,特别是对于像我这样的初学者。) 然后,我编写了一个新函数 primeLis

  • 超过了最大更新深度。当组件重复调用组件WillUpdate或组件DidUpdate中的setState时,可能会发生这种情况。React限制嵌套更新的数量以防止无限循环。 这是bossinfo.js 这是user.redux.js 你为什么一直报告这个问题?这是指向错误的方向吗?寻求帮助

  • 这是我的代码: 首先,我从一个列表中做一个二叉查找树,并检查它是否是一个二叉查找树。 给定列表的第一个元素是根节点,后续元素成为子节点。到叶节点。 例如,调用 的结果为: 结果是二叉搜索树,因为左子节点小于父节点,右子节点大于父节点。因此,调用<code>bst_child</code>的结果是<code>True</code>。 然后我添加了寻找二叉查找树深度的代码。通过对第一个列表排序,我制作