[英]Convert recursive function to iterative function
尽管这似乎是重复的(也许是重复的,但是我还没有找到针对该问题版本的解决方案),但我认为不是。
下面是我的递归函数,它破坏了python的递归限制,而我需要使其进行迭代,但是在查看如何实现方面遇到了问题。
def countChain(n, cache):
if cache[n] != -1:
return cache[n]
if n % 2 == 0:
cache[n] = 1 + countChain(n / 2, cache)
else:
cache[n] = 2 + countChain((3 * n + 1) / 2, cache)
return cache[n]
请注意,这里的缓存列表中有100万个元素...(这就是递归杀死python的原因)。 我已经看到人们使用累加器来完成这项工作,但是在这里,我没有直接返回递归调用的结果,这使此想法难以实现。
编辑
第一个递归调用应该是cache[n] = 1 + countChain(n / 2, cache)
而不是cache[n] = 1 + countChain(n, cache)
编辑2
有人要求提供数据,所以我将简单地输入整个代码(不那么长)以更好地理解。
import time
import sys
import math
def main():
target = int(sys.argv[1])
start = time.time()
longest = 0
answer = -1
for i in range(int(target/2), target):
if countChain(i) > longest:
longest = countChain(i)
answer = i
print("Result = ", answer, " in ", (time.time() - start), " seconds")
def countChain(n,cache={1:0}):
if n not in cache:
if n % 2 == 0:
cache[n] = 1 + countChain(n//2, cache)
else:
cache[n] = 2 + countChain((3 * n + 1) // 2, cache)
return cache[n]
if __name__ == "__main__":
main()
通常的输入是1000000
另外,其他应该是2 + ...
三种版本: 自然递归和缓存的一种:
def countchain_recursive_cache(n):
if n not in cache:
if n % 2 == 0:
cache[n] = 1 + countchain_recursif(n//2)
else:
cache[n] = 1 + countchain_recursif(3 * n + 1)
return cache[n]
一种纯粹的迭代方法:
def countchain_iterative(n):
count=0
while n>1:
if n%2 == 0 :
n //= 2
count += 1
else :
n = (3*n+1)//2
count += 2
return count
和无堆栈的缓存版本:
def countchain_iterative_cache(n):
count = 0
n0=n
while n not in cache:
count += 1
if n%2 == 0 : n //= 2
else : n = 3*n+1
count+= cache[n]
n=n0
while n not in cache:
cache[n]=count
count-=1
if n%2 == 0 : n //= 2
else : n = 3*n+1
return cache[n]
如果缓存在函数中,则缓存机制不起作用。 它必须是全球性的,以加速进一步的通话。
这些时间是:
%time for i in range(1,10**4) : countchain_iterative(i)
cache={1:0}
%time for i in range(1,10**4) : countchain_iterative_cache(i)
cache={1:0}
%time for i in range(1,10**4) : countchain_recursive_cache(i)
%time for i in range(1,10**4) : countChain_morcedist(i)
# respectively :
Wall time: 490 ms
Wall time: 80 ms
Wall time: 54 ms
Wall time: 3.82 s
但是,如果您只想要一个计数链,则使用非缓存的迭代方法是最有效的方法:
%time countchain_iterative(10**10_000)
Wall time: 6.37 s
Out[381]: 177856
最后,我猜想您永远不会在迭代构造中使快速递归函数崩溃:
%time for i in range(1,10**7): countchain_recursif(i)
Wall time: 1min 8s
您始终可以通过使用堆栈将递归函数转换为迭代函数。 这是我的处理方式:
def countChain(n):
cache = { 1: 0 }
stack = [n]
while n not in cache:
n_curr = stack.pop()
if n_curr % 2 == 0:
if n_curr / 2 in cache:
cache[n_curr] = 1 + cache[n_curr / 2]
else:
stack.append(n_curr)
stack.append(n_curr / 2)
else:
if (3 * n_curr + 1) / 2 in cache:
cache[n_curr] = 3 + cache[(3 * n_curr + 1) / 2]
else:
stack.append(n_curr)
stack.append((3 * n_curr + 1) / 2)
return cache[n]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.