所以我有一个递归的解决方案,有时会改变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
但它需要永远。让它在一秒钟之内运行是理想的。
答案 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))
时不会烧掉堆栈。