Java 关于递归方法代码的问题
我对这个代码有一些问题Java 关于递归方法代码的问题,java,string,recursion,substring,Java,String,Recursion,Substring,我对这个代码有一些问题 public static String reverseString( String s ) { if ( s.length() == 0 ) return ""; String firstChar = s.substring( 0, 1 ); String reverseRest = reverseString( s.substring( 1 ) ); String result = reverseRest + firstChar; r
public static String reverseString( String s )
{
if ( s.length() == 0 )
return "";
String firstChar = s.substring( 0, 1 );
String reverseRest = reverseString( s.substring( 1 ) );
String result = reverseRest + firstChar;
return result;
}
public static void main( String[] args )
{
String a = "The sky's the limit!";
System.out.println( reverseString( a ) );
}
问题1:终止情况究竟如何运作?s.length将如何等于0
问题2:为什么代码需要“firstChar”才能反转字符串?当reverseString接受子字符串0且不必添加第一个字符时,为什么代码不起作用
问题1:终止情况究竟如何运作?怎么
s.length是否永远等于0
如果您阅读,那么您将理解它返回的子字符串以指定的字符开始,并一直延伸到结尾。由于您指定起始字符1,并且字符以0开始编号,子字符串(1)
本质上意味着“以第二个字符开始”。这样,嵌套调用的字符串长度正好减少一个字符。当然,它最终会达到0!当从长度为1的字符串中获取子字符串(1)时,它将达到0,因为对于这样的字符串,“从第二个字符开始”意味着一个空子字符串
问题2:为什么代码需要“firstChar”才能
把绳子倒过来?为什么反向限制时代码不起作用
接受0的子字符串,并且不必添加第一个字符
这就是递归的意义所在。如果取第一个字符,反转字符串的其余部分,然后将该字符附加到字符串的其余部分的末尾,如果不是反转字符串,会得到什么
或者,如果你想要严谨,这是一件光荣的事情,那么让我们用正确的方式来做。让我们首先证明这个函数正确地反转了长度为0的字符串
反转的空字符串就是空字符串本身。由于当输入字符串为空时,代码显式返回一个空字符串(顺便说一句,为了清楚起见,最好将length()==0
替换为isEmpty()
),这证明该函数适用于0长度字符串。那没那么难吧
现在让我们证明,如果该函数适用于长度为i
(i>=0
)的字符串,那么它也适用于长度为i+1
的字符串。假设s.length()==i+1
。我们取第一个字符,然后调用反向字符串(s.substring(1))
。此调用的参数是长度为i
的字符串,因为它比s
短一个字符。因为我们假设我们的函数对于长度为i
的字符串非常有效,所以结果是字符串的正确反转子字符串,从字符1(第二个)开始。然后,我们将s
的第一个字符附加到此字符串,从而使长度i+1
的s
正确反转
我们已经证明它适用于长度0
,因此从我们的第二个证明可以看出,它也适用于长度1
。但从这一点来看,它也适用于长度2
。等等,等等。。。这就是证明递归函数工作的方法
现在,如果不添加第一个字符,会发生什么。假设该函数对于较短的字符串(子字符串(1)
)工作正常,那么最终得到的字符串将短一个字符。短一个字符的字符串显然不会与原始字符串相反,因此,如果只反转子字符串(1)
,而不向结果添加任何内容,则证明此函数不可能工作
如果在递归调用中传递子字符串(0),会发生什么?这是另一个有趣的问题。在证明的第二部分中,我们假设该函数适用于较短的字符串。在这种情况下,子字符串(0)
不是较短的字符串。事实上,它是原始字符串本身,因此传递子字符串(0)
相当于只传递s
。所以我们的证据不再有效了。此外,由于我们正在进行相同的调用,它将继续一次又一次地调用自己,直到递归变得太深时得到StackOverflowerError
因此,整个想法是基于将手头的任务分解为更小的部分,而子字符串(0)
不是更小的部分。另一个有趣的任务是将字符串分成两半,而不是仅仅切掉一个字符,然后返回reverseString(右)+reverseString(左)
。我建议您尝试这样做(注意奇数/偶数长度),看看它是否有效,并证明它是如何工作的
问题1:终止情况究竟如何运作?怎么
s.length是否永远等于0
如果您阅读,那么您将理解它返回的子字符串以指定的字符开始,并一直延伸到结尾。由于您指定起始字符1,并且字符以0开始编号,子字符串(1)
本质上意味着“以第二个字符开始”。这样,嵌套调用的字符串长度正好减少一个字符。当然,它最终会达到0!当从长度为1的字符串中获取子字符串(1)时,它将达到0,因为对于这样的字符串,“从第二个字符开始”意味着一个空子字符串
问题2:为什么代码需要“firstChar”才能
把绳子倒过来?为什么反向限制时代码不起作用
接受0的子字符串,并且不必添加第一个字符
这就是递归的意义所在。如果取第一个字符,反转字符串的其余部分,然后将该字符附加到字符串的其余部分的末尾,如果不是反转字符串,会得到什么
或者,如果你想要严谨,这是一件光荣的事情,那么让我们用正确的方式来做。让我们首先证明这个函数可以反转长度为0的字符串