我还是相对较新的Python,我刚刚写了一个执行Collatz Conjecture.的基本程序但是,我遇到了堆栈溢出,因为我已经递归地编写了程序,而不是迭代(根据本网站上的其他问题)。这个问题还有其他一些答案,但我不确定如何在我自己的程序中实现它们。简化版如下:(编辑:我刚刚翻译了一些代码以使其更简单,我实际上遇到了运行此问题的问题,但你知道发生了什么 - pastebin of actual code)
def collatz(number):
if number == 1:
print('Finished!')
if number % 2 == 0:
number = number/2
collatz(number)
elif number % 2 != 0:
number = (number*3) + 1
collatz(number)
n = int(input('Pick a number'))
collatz(n)
这看起来相当简单,但我似乎无法理解这一点。我尝试了一个更简单的例子:
def fun(n):
while n < 10:
n += 1
fun(n)
fun(1)
我试图通过迭代我在本网站上看到的例子来转换它
def fun(n):
while n < 10:
n += 1
return n
fun(1)
但我不确定如何实现n
的返回来迭代程序。
如果这是一个补救性问题,我道歉,但我似乎无法克服这个问题。
编辑:
下面还有一些很好的通用解决方案。
答案 0 :(得分:3)
一般来说,你的后两个例子是:
def recr_fun(n):
if n >= 10:
return n
return recr_fun(n+1)
def iter_fun(n):
while n < 10:
n += 1
return n # note identation
请注意,递归版本必须通过递归调用将结果传递回来,并且迭代版本在循环完成后返回。
答案 1 :(得分:1)
你是对的,while
循环在这里可以正常工作:
def collatz(number):
number = int(number)
while number != 1:
if number % 2 == 0:
number = number/2
elif number % 2 != 0: # could be just `else` -- either it's divisible by 2 or it isn't :)
number = (number*3) + 1
print("finished")
n = int(input('Pick a number'))
collatz(n)
在这种情况下,非递归形式主义实际上更清晰,因为你的函数实际上并没有返回任何东西。
答案 2 :(得分:1)
完成后你忘记了回来:
def collatz(number):
if number == 1:
print('Finished!')
return # you are causing an infinite loop if you dont do this
if number % 2 == 0:
number = number/2
collatz(number)
elif number % 2 != 0:
number = (number*3) + 1
collatz(number)
您可以像下面那样清理代码:
def collatz(number):
if number == 1:
print('Finished!')
return # you are causing an infinite loop if you dont do this
if number % 2 == 0: collatz(number/2)
else: collatz((number*3) + 1)
干杯!
答案 3 :(得分:0)
由于程序不正确,您会收到堆栈溢出:
def collatz(number):
if number == 1:
print('Finished!')
elif number % 2 == 0:
number = number/2
collatz(number)
elif number % 2 != 0:
number = (number*3) + 1
collatz(number)
这项工作很好没有堆栈溢出。但是,代码的迭代版本是
def iterCollatz(number):
while number != 1:
if number % 2 == 0:
number = number / 2
else:
number = (number * 3) + 1
print('Finished!')
答案 4 :(得分:0)
在大多数情况下,没有办法在算法上说'#34;如果我在这个递归函数上执行这些操作,它就会变为迭代。&#34;相反,你需要查看整个程序并查看它是如何工作的,然后了解如何使它在没有递归的情况下工作。例如,让我们编写一个递归解决方案来展平列表(包含列表和数字等)
def recurse_flatten(target):
"""recurse_flatten(list_of_lists) -> flat list"""
accumulator = list()
for element in target:
if hasattr(element,"__iter__"):
accumulator.extend(recurse_flatten(element))
else:
accumulator.append(element)
return accumulator
如您所见,如果顶级元素具有属性"__iter__"
,则该函数会调用自身,这意味着它可以迭代。相反,我们可以这样做:
def iter_flatten(target):
"""iter_flatten(list_of_lists) -> flat list"""
depth = 0
targets = [iter(target)]
accumulator = list()
while True:
try:
element = next(targets[depth])
except StopIteration:
if depth == 0: return accumulator
else:
depth -= 1
targets.pop()
else:
if hasattr(element,"__iter__"):
targets.append(iter(element))
depth += 1
else: accumulator.append(element)
正如您所看到的,迭代版本更长,更冗长,但它永远不会嵌套。如果你有有限的堆栈空间,这可能是一件好事,但一般来说(至少如果你正在编写Python)代码越可读,就越好,让我现在告诉你,递归代码是更加可读。时间明智,你必须自己测试。在我的系统上:
# TEST DATA: [1, 2, [3, 4, 5, 6], 7, [8, [9, 10, 11]]]
# timeit.timeit(recurse_flatten)
10.985460426787078
# timeit.timeit(iter_flatten)
16.635406831330158