Python 3.x 在python中进行更改(相比之下超过了最大递归深度)

Python 3.x 在python中进行更改(相比之下超过了最大递归深度),python-3.x,recursion,Python 3.x,Recursion,所以我有一个递归的方法来解决makechange问题,这个方法有时会奏效。它是: def change(n, c): if (n == 0): return 1 if (n < 0): return 0; if (c + 1 <= 0 and n >= 1): return 0 return change(n, c - 1) + change(n - coins[c - 1], c); 我得到一个: Recur

所以我有一个递归的方法来解决makechange问题,这个方法有时会奏效。它是:

def change(n, c):
   if (n == 0):
      return 1

   if (n < 0):
      return 0;

   if (c + 1 <= 0 and n >= 1):
      return 0

   return change(n, c - 1) + change(n - coins[c - 1], c);
我得到一个:

RecursionError: maximum recursion depth exceeded in comparison
所以我的问题是,什么是优化这个的最好方法。使用某种流量控制?我不想做这样的事

# Set recursion limit
sys.setrecursionlimit(10000000000)   
更新:

我现在有点像

def coinss(n, c):

   if n == 0:
      return 1

   if n < 0:
      return 0

   nCombos = 0
   for c in range(c, -1, -1):
      nCombos += coinss(n - coins[c - 1], c)


   return nCombos
def coins(n,c):
如果n==0:
返回1
如果n<0:
返回0
nCombos=0
对于范围(c,-1,-1)内的c:
nCombos+=硬币(n-硬币[c-1],c)
返回nCombos

但这需要永远。最好能在一秒钟内运行此程序。

使用递归时,您将始终遇到此问题。如果将递归限制设置得更高,则可以在更大的数字上使用算法,但始终会受到限制。递归限制是为了防止堆栈溢出

解决较大变更量的最佳方法是采用迭代方法。维基百科上有一些算法:

正如上面的答案所建议的,您可以使用DP来获得更优的解决方案。 还有你的有条件支票-
如果(c+1=1)

应该是


if(c=1和c注意这里有一个bug:

if (c + 1 <= 0 and n >= 1):
迭代/堆栈方法(非动态规划),不递归,只使用“堆栈”存储要执行的计算:

def change2(n):
    def change_iter(stack):
        result = 0
        # continue while the stack isn't empty
        while stack:
            # process one computation
            n,c = stack.pop()
            if n == 0:
              # one solution found, increase counter
              result += 1

            if n > 0 and c > 0:
                # not found, request 2 more computations
                stack.append((n, c - 1))
                stack.append((n - coins[c - 1], c))

        return result
    return change_iter([(n,len(coins))])
对于
n
的低值,这两种方法返回相同的值

for i in range(1,200):
    a,b = change(i),change2(i)
    if a != b:
        print("error",i,a,b)
上面的代码运行时没有任何错误


现在<代码>打印(更改2(1000))
需要几秒钟,但打印
142511
时不会破坏堆栈。

总之,您应该将此视为您对非递归问题采用递归方法的标志。您的问题看起来像是动态编程解决方案的教科书示例。@PatrickHaugh您没有错。我有DP解决方案。请尝试ing需要精益一些东西。例如,如果上述解决方案可以优化为运行“更快”使用递归。通常不会。递归的优点是它可以生成简单、干净的代码,而且人的问题是递归的,因此有自然的递归解决方案。特别是在Python这样的语言中,递归算法不优化,递归可能会非常昂贵。Arg,是的,我知道如何使用DP解决方案。请注意我刚刚接触python,我正在研究如何优化上面的代码。我喜欢这个答案。但我仍然认为它需要是c+1。你从来没有说过启动
c
len(coins)-1
,所以我使用
len(coins)
。如果
c+1==1
,那么
c
可以是0,而
coins[c-1]
错误:它使用最后一个项目(25)而不是前一个项目。嗯,我说“c是硬币数组的长度-1”…那么我的解决方案是错误的?那么这可能会导致溢出?好的,但是你的程序仍然存在问题。你不需要知道硬币数组的长度。你可以通过使用
len(硬币)来去掉该参数
内部。在解决方案中只使用硬币1和硬币5进行检查,然后尝试输入5:您将得到3,而实际的解决方案是2。但这并不会导致溢出。太多递归调用会导致溢出是的,因此问题就来了。我正试图找到一个不会溢出堆栈的递归解决方案。在fo中玩递归调用现在是r环。
coins = [1,5,10,25]

def change(n):
    def change_recurse(n, c):
       if n == 0:
          return 1

       if n < 0:
          return 0;

       if c <= 0:
          return 0

       return change_recurse(n, c - 1) + change_recurse(n - coins[c - 1], c)
    return change_recurse(n,len(coins))
def change2(n):
    def change_iter(stack):
        result = 0
        # continue while the stack isn't empty
        while stack:
            # process one computation
            n,c = stack.pop()
            if n == 0:
              # one solution found, increase counter
              result += 1

            if n > 0 and c > 0:
                # not found, request 2 more computations
                stack.append((n, c - 1))
                stack.append((n - coins[c - 1], c))

        return result
    return change_iter([(n,len(coins))])
for i in range(1,200):
    a,b = change(i),change2(i)
    if a != b:
        print("error",i,a,b)