是否可以将此递归解决方案(打印括号)转换为迭代版本?
我需要打印打印有效标签“<”的不同变体和“>”给定标签应该出现的次数,下面是 python 中使用递归的解决方案。
def genBrackets(c):
def genBracketsHelper(r,l,currentString):
if l > r or r == -1 or l == -1:
return
if r == l and r == 0:
print currentString
genBracketsHelper(r,l-1, currentString + '<')
genBracketsHelper(r-1,l, currentString + '>')
return
genBracketsHelper(c, c, '')
#display options with 4 tags
genBrackets(4)
我很难真正理解这一点,并想尝试将其转换为迭代版本,但我没有取得任何成功。
根据此线程: 每个递归都可以转换为迭代吗? -看起来应该是可能的,唯一的例外似乎是阿克曼函数。
如果有人对如何查看 Eclipse 中维护的“堆栈”有任何提示 - 我们也将不胜感激。
附言。这不是一个家庭作业问题 - 我只是想更好地理解递归到迭代的转换。
由 Matthieu M 编辑。 更好可视化的输出示例:
>>> genBrackets(3)
<<<>>>
<<><>>
<<>><>
<><<>>
<><><>
I need to print the different variations of printing valid tags "<" and ">" given the number of times the tags should appear and below is the solution in python using recursion.
def genBrackets(c):
def genBracketsHelper(r,l,currentString):
if l > r or r == -1 or l == -1:
return
if r == l and r == 0:
print currentString
genBracketsHelper(r,l-1, currentString + '<')
genBracketsHelper(r-1,l, currentString + '>')
return
genBracketsHelper(c, c, '')
#display options with 4 tags
genBrackets(4)
I am having a hard time really understanding this and want to try to convert this into a iterative version but I haven't had any success.
As per this thread: Can every recursion be converted into iteration? - it looks like it should be possible and the only exception appears to be the Ackermann function.
If anyone has any tips on how to see the "stack" maintained in Eclipse - that would also be appreciated.
PS. This is not a homework question - I am just trying to understand recursion-to-iteration conversion better.
Edit by Matthieu M. an example of output for better visualization:
>>> genBrackets(3)
<<<>>>
<<><>>
<<>><>
<><<>>
<><><>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我试图保持与您的代码基本相同的结构,但使用显式堆栈而不是对 genBracketsHelper 的函数调用:
请注意,我使用的转换依赖于位于末尾的所有递归调用功能;如果不是这样的话,代码会更复杂。
I tried to keep basically the same structure as your code, but using an explicit stack rather than function calls to
genBracketsHelper
:Note that the conversion I am using relies on all of the recursive calls being at the end of the function; the code would be more complicated if that wasn't the case.
您询问如何在没有堆栈的情况下执行此操作。
该算法遍历整个解决方案空间,因此它比原始版本做了更多的工作,但它基本上是相同的概念:
由于每条路径都是二进制决策序列,因此路径对应于整数的二进制表示0 到 2**(c*2)-1 之间。
所以:只需循环这些数字,看看二进制表示是否对应于平衡字符串。 :)
You asked about doing this without a stack.
This algorithm walks the entire solution space, so it does a bit more work than the original versions, but it's basically the same concept:
Since each path is a sequence of binary decisions, the paths correspond to the binary representations of the integers between 0 and 2**(c*2)-1.
So: just loop through those numbers and see if the binary representation corresponds to a balanced string. :)
一般来说,递归会创建一个调用树,根是原始调用,叶子是不递归的调用。
一种退化情况是每个调用仅执行一个其他调用,在这种情况下,树退化为一个简单列表。然后,只需使用堆栈即可实现到迭代的转换,如 @Jeremiah 所示。
在更一般的情况下,就像这里一样,当每个调用执行多个(严格)多个调用时。您获得了一棵真正的树,因此有多种方法可以遍历它。
如果您使用队列而不是堆栈,那么您将执行广度优先遍历。 @Jeremiah 提出了一个我不知道名字的遍历。典型的“递归”顺序通常是深度优先遍历。
典型递归的主要优点是堆栈的长度不会增长那么多,因此您通常应该以深度优先为目标......如果复杂性不会压垮您:)
我建议首先编写深度优先遍历一棵树,一旦完成,使其适应您的算法应该相当简单。
编辑:因为我有一些时间,所以我编写了Python树遍历,这是典型的示例:
请注意,由于需要记住我们当前正在访问的子项的索引,因此堆栈管理稍微复杂一些。
算法的适应遵循深度优先顺序:
我刚刚意识到存储索引有点“太”复杂,因为我从来没有回来过。因此,简单的解决方案包括删除我不再需要的列表元素,将列表视为队列(事实上,堆栈就足够了)!
这适用于最小变换。
In general, a recursion creates a Tree of calls, the root being the original call, and the leaves being the calls that do not recurse.
A degenerate case is when a each call only perform one other call, in this case the tree degenerates into a simple list. The transformation into an iteration is then simply achieved by using a stack, as demonstrated by @Jeremiah.
In the more general case, as here, when each call perform more (strictly) than one call. You obtain a real tree, and there are, therefore, several ways to traverse it.
If you use a queue, instead of a stack, you are performing a breadth-first traversal. @Jeremiah presented a traversal for which I know no name. The typical "recursion" order is normally a depth-first traversal.
The main advantage of the typical recursion is that the length of the stack does not grow as much, so you should aim for depth-first in general... if the complexity does not overwhelm you :)
I suggest beginning by writing a depth first traversal of a tree, once this is done adapting it to your algorithm should be fairly simple.
EDIT: Since I had some time, I wrote the Python Tree Traversal, it's the canonical example:
Note that the stack management is slightly complicated by the need to remember the index of the child we were currently visiting.
And the adaptation of the algorithm following the depth-first order:
I just realized that storing the index is a bit "too" complicated, since I never visit back. The simple solution thus consists in removing the list elements I don't need any longer, treating the list as a queue (in fact, a stack could be sufficient)!
This applies with minimum transformation.
是的。
输出顺序不同,但结果应该是一样的。
Yes.
The output order is different, but the results should be the same.