在python中进行更改(比较时超出最大递归深度)

时间:2018-04-26 19:50:19

标签: python-3.x recursion

所以我有一个递归的解决方案,有时会改变make make的问题。它是:

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);

其中硬币是我的硬币阵列。例如[1,5,10,25]。 n是硬币的数量,例如1000,c是硬币阵列的长度 - 1.此解决方案适用于某些情况。但是当我需要它在两秒钟内运行时我会使用:

coins: [1,5,10,25]
n: 1000

我得到了:

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

但它需要永远。让它在一秒钟之内运行是理想的。

3 个答案:

答案 0 :(得分:1)

如上面的答案所示,您可以使用DP获得更优化的解决方案。 还有条件检查 - if (c + 1 <= 0 and n >= 1)

应该是

if (c <= 1 ):

因为n将始终为&gt; = 1并且如果硬币数量小于或等于1,则c <= 1将阻止任何计算。

答案 1 :(得分:0)

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

解决更大变化量的最佳方法是交换迭代方法。那里有算法,维基百科: https://en.wikipedia.org/wiki/Change-making_problem

答案 2 :(得分:0)

请注意,您有一个错误:

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

就像

if (c <= -1 and n >= 1):

所以c可以为0并传递到下一步,将c-1传递给索引,这是因为python不介意负索引但仍然是假的({{1} } yield coins[-1]),因此您的解决方案有时会打印出太多的组合。

我用递归和堆栈方法重写了你的算法:

递归(修复,由于内部递归方法,在初始化时不需要25,但仍然溢出堆栈):

c

迭代/堆栈方法(不是动态编程),没有递归,只是使用&#34;堆栈&#34;存储要执行的计算:

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))]) 的低值返回相同的值。

n

上面的代码运行时没有任何错误打印。

现在for i in range(1,200): a,b = change(i),change2(i) if a != b: print("error",i,a,b) 需要几秒钟,但打印print(change2(1000))时不会烧掉堆栈。