这是一个递归方法:
public static String reverseRecursively(String str) {
//base case to handle one char string and empty string
if (str.length() < 2) {
return str;
}
System.out.println(str.substring(1) + " "+ str.charAt(0));
return reverseRecursively(str.substring(1)) + str.charAt(0);
}
显然它应该反转String
。我从这个方法得到的输出是:
23456 1
3456 2
456 3
56 4
6 5
654321
工作正常。但问题是,我不明白 它是如何运作的。看完输出后,我完全糊涂了。我理解的是,它返回的是截断的String
,它越来越短。有人可以解释一下这是如何起作用的吗?
答案 0 :(得分:4)
首先从这个字符串开始:
"123456"
它首先达到了这个条件:
if (str.length() < 2) {
return str;
}
String
超过1个字符,因此在此处不执行任何操作。下一个执行的方法是:
System.out.println(str.substring(1) + " "+ str.charAt(0));
为简单起见,我们只关注内部部分:
str.substring(1) + " " + str.charAt(0)
所以这里有两种方法substring(int)
和charAt(int)
。
substring(int)
:此方法返回,因为名称暗示原始字符串的子字符串。它从您传递给方法的索引开始。charAt(int)
:这会返回String
。现在,如果我们再次查看方法中的代码,请记住当前str是&#34; 123456&#34;。
如果我们在此substring(1)
上使用String
,则会返回从索引1开始的所有内容,因此substring(1)
会返回&#34; 23456&#34;。只剩下第一个字符了。
如果我们使用charAt(0)
,我们会在String
m中找到第一个字符,因此charAt(0)
只返回&#34; 1&#34;。
现在我们知道第一次迭代中这些方法返回的值是什么:
str.substring(1) + " " + str.charAt(0) = "23456 1"
| |
V V
"23456" + " " + "1" = "23456 1"
然后递归开始:
return reverseRecursively(str.substring(1)) + str.charAt(0);
因此str.substring(1)
的值现已传递到reverseRecursively()
。这里的str.charAt(0)
只会在String
返回后附加到reverseRecursively()
。换句话说,它看起来像这样:
return reverseRecursively("23456") + "1";
在下一次迭代中,一切都重新开始,唯一的区别是现在reverseRecursively()
以String
&#34; 23456&#34;而不是&#34; 123456&#34;。所以最终会归结为:
return reverseRecursively("3456") + "2" + "1";
再次在下一次迭代中,它可以解决这个问题:
return reverseRecursively("456") + "3" + "2" + "1";
这种情况一直持续到String
传入reverseRecursively()
的长度小于2,所以一旦递归到达此值:
reverseRecursively("6")
if语句将启动并返回String
"6"
。
if (str.length() < 2) {
return str;
}
所以最终结果将是:
"6" + "5" + "4" + "3" + "2" + "1" = "654321"
总结一下:
这种方法的作用是从
String
获取所有内容 第一个字符和第一个字符添加到结尾 将String
的其余部分再次传入后再String
reverseRecursively()
再次导致第一个角色出现 附加到最后,其他一切都重新开始。整个东西String
达到1的长度后停止。
所以这一切归结为:
"123456"
"23456" + "1"
"3456" + "2" + "1"
"456" + "3" + "2" + "1"
"56" + "4" + "3" + "2" + "1"
"6" + "5" + "4" + "3" + "2" + "1" = "654321"
我希望我能正确解释算法!如果您有任何其他问题,请随时询问!
答案 1 :(得分:1)
它的工作方式与递归函数的工作方式相同。它会递归调用,直到遇到终止条件:str.length() < 2
在这种情况下。然后返回最后/最深的函数调用,然后调用函数调用也返回,并且其调用函数调用也返回,依此类推。然后你得到了结果。
答案 2 :(得分:1)
有几种方法可以使用递归来反转字符串,这个特殊的例子会在堆栈展开时生成反向字符串。
下图可能有所帮助,您在调用发生时打印出参数(被推入堆栈)。这是在它展开时发生的事情。在每一行我都用它的递归调用替换了对rev的调用,这是对rev和串联的另一个调用。直到字符串少于两个字符,此时它才会停止。
rev("1234")
rev("234") + "1"
(rev("34") + "2") + "1"
((rec("4") + "3") + "2") + "1"
(("4" + "3") + "2") + "1"
答案 3 :(得分:0)
这是一个反向打印字符串的方法。
public static void reverseRecursively(String str) {
//Base case
if (str.length() < 2) {
System.out.println(str);
return;
}
//Recursive Call the string without the first charecter
reverseRecursively(str.substring(1));
//print the first char of the string
System.out.println(str.charat(0));
}
好的,这里发生的是当你调用函数时传递参数'str'。对于这个例子,我们可以说str的值是“Waffle”。由于我们的字符串太长,因此无法满足基本情况。下一行代码是递归调用。 “affle”传递给新功能。由于我们已经在函数内部,因此它的所有内存都被推送到“堆栈帧”。这会快照“str”的值并将其放在一边供以后使用。视觉表示:
“华夫饼” - &gt;传递给recursiveFunction 没有基本的符合 调用新的recursiveFunction 当New函数返回时,将保存堆栈帧 “affle” - &GT;传递给recursiveFunction 没有基础符合 调用新的recursiveFunction 推送另一个堆栈框架保存“affle” “ffle”被传递给新的递归函数
重复此过程,直到满足基本大小写。一旦调用了返回值('str'的值=“e”,我的函数在返回之前打印“e”),stackFrame弹出并且'str'的值返回到前一个值“le”。下一行是打印状态,打印出str的第一个字符,以便打印“l”。
重复此操作,直到所有帧都已完成运行。
导致看起来像这样的consol: Ë 升 F F 一个 瓦特