将递归函数变成for循环?
每个递归函数都有一个等效的 for 循环吗? (两者达到相同的结果)。
我有这个递归函数:
private static boolean recur(String word, int length) {
if(length == 1 || length == 2)
return false;
if(length == 0)
return true;
if(words[length].contains(word.substring(0, length)))
return recur(word.substring(length), word.length() - length);
return recur(word, length-1);
}
假设单词是一个 Set[],并且单词 [i] = 单词长度为 i 的集合。
我想做的是: 用一个单词(比如“stackoverflow”,没有空格)启动递归,我试图找出这个单词是否可以被切成子单词(“stack”,“over”,“flow”)..子单词的最小长度是 3,并且假设长度 i 的子字在 Set Words[i] 中。
我可以确认这段代码有效,但它可能有内存问题,所以我想将其转换为循环..如果可能的话。
您需要更多信息吗?
谢谢。
Does every recursive function have an equivalent for loop? (Both achieve the same result).
I have this recursive function:
private static boolean recur(String word, int length) {
if(length == 1 || length == 2)
return false;
if(length == 0)
return true;
if(words[length].contains(word.substring(0, length)))
return recur(word.substring(length), word.length() - length);
return recur(word, length-1);
}
Given that words is a Set[], and where words[i] = a set with words of length i.
What am trying to do is:
initiate the recursion with a word (say, "stackoverflow", no spaces), I am trying to find if this word can be cut into subwords ("stack", "over", "flow") .. minimum length of a subword is 3, and given that the subword of lenght i is in the Set words[i].
I can confirm this code works, but it may have a memory problem, so I want to turn it to a loop.. if possible.
Do you need more info??
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
尾递归始终可以展开为循环,并且您的代码
非常接近尾递归,所以是的。现在这就是正确的尾递归。现在将其变成循环:
请注意,这段代码可以进一步优化,我只是想演示将递归变成循环的“自动”方法。
Tail recursion can always be unrolled into a loop and your code is
pretty close totail recursion, so yes.This is now proper tail recursion. Now to turn it into a loop:
Note that this code can be further optimised, I just wanted to demonstrate the "automatic" method of turning recursion into a loop.
对于一般问题:是的,每个递归都可以在循环中进行转换。您可以显式地对递归创建和使用的堆栈进行建模,并在循环中对其进行修改。
对于具体问题:
将代码视为函数并忽略副作用,我认为您可以返回 false。
如果您确实需要拆分词,请尝试以下操作:
For the general question: Yes every recursion can be transformed in a loop. You can model the the stack created and used by recursion explicitely and modify it in the loop.
For the specific problem:
Looking at your code as a function and ignoring side effects I think you could just return false.
If you actually need the split words try the following:
简短的回答:一般来说你可以,在这种情况下你可以很容易地做到,但是如果你修复了代码逻辑中的错误,你就必须担心自己维护堆栈。
长答案:
首先,递归方法的迭代版本:
它的工作原理是用参数赋值替换递归调用,并将其全部放入循环中。
但就像您的原始代码一样,这包含一个错误!
(我想不出这个 bug 所使用的实际单词,所以想象一下我编造的单词是真实的单词。)
假设您的长单词是 ABCDEFGH,并且 ABCD、EFGH 和 ABCDE 都是单词,但 FGH 不是。
recur
首先查找最长的单词,所以会匹配ABCDE,然后发现FGH不是单词,并告诉你ABCDEFGH不能切成子词。但它可以分为ABCD和EFGH!它会错过较短的初始匹配,因为一旦找到匹配,您就不会考虑其他选项。 (如果你的代码从寻找较短的匹配开始,如果 ABC 是一个单词而 DEFGH 不是一个单词,它仍然无法工作。)
所以:
现在,将其转换为迭代方法更困难:有时你有 两次递归调用。这意味着简单地分配给参数是行不通的,因为您需要参数的原始值来计算第二次调用的参数。您必须显式管理具有所有不同值的堆栈或队列,因为现在该语言无法为您执行此操作。
Short answer: in general you can, in this case you can easily, but if you fix the bug in your code's logic you have to worry about maintaining a stack yourself.
Long answer:
First, the iterative version of your recursive method:
This works by replacing the recursive call with assignment to the parameters, and sticking it all in a loop.
But like your original code, this contains a bug!
(I can't think of actual words that this bug works with, so imagine my made up words are real words.)
Suppose your long word is ABCDEFGH, and that ABCD, EFGH, and ABCDE are all words, but FGH isn't.
recur
looks for the longest word first, so it will match ABCDE, then discover that FGH isn't a word, and tell you that ABCDEFGH can't be cut into subwords.But it could be split into ABCD and EFGH! It misses the shorter initial match because you don't consider other options once you've found a match. (And if your code started by looking for the shorter match, it still wouldn't work if ABC was a word and DEFGH wasn't.)
So:
Now, turning this into an iterative method is harder: sometimes you have two recursive calls. That means simply assigning to your parameters won't work, because you need the parameters' original values to calculate the parameters for the second call. You have to explicitly manage a stack or a queue with all the different values, because now the language isn't doing it for you.
我回答你的第一个问题:是的,每个递归函数都有一个迭代函数。 了解更多。
这也与 CPS 有关(不完全是因为尾部调用不受真正支持由流行的 Java VM 提供)。转换尾递归函数(例如问题中的函数)应该特别容易。
I answer your first question: Yes, every recursive function has an iterative equivalent. Read more.
This also is kind of related to CPS (not exactly because tail calls aren't really supported by popular Java VMs). Converting a tail recursive function (such as the one in the question) should be especially easy.
@biziclop 演示了如何将代码重构为非递归的。我会进一步减少代码,以便。
length
不再作为参数传递。代码
@biziclop demonstrates how to refactor the code to be non recursive. I would go further and reduce the code so that.
length
is no longer passed as an argument.code