递归算法深入浅出四:递归判断回文串以及递归辅助方法


递归算法概述及常见算法列表,传送门:
http://blog.csdn.net/nthack5730/article/details/65537530


写在前面

这篇是写关于递归的第四篇文章了,本文除了关于回文串的递归实现方法外,还涉及到【递归辅助方法】观点和思路。
其实慢慢下来,基础的递归问题的设计不算难。都是基于递归的几大特性进行设计(特性详见:递归理论概述和常见递归算法罗列,有解说)。
至于稍难的递归例如:汉诺塔、八皇后…等这些会在慢慢深入的过程中将自己的想法思路和大家分享\~\~\~如果大家有不同的思路或想法,真心欢迎大家评论交流

回文串

“回文串”是一个从左读和从右读都一样的字符串,比如“level”或者“noon”等等就是回文串。
常见的回文串有:dad,123454321,123456654321….

回文串判断、定义

  • 字符串中的前后两端的字符都是对称的
  • 去掉前后两端的字符,剩下的字符串中的字符两端是否相等
  • 依次类推,直到剩余的字符串长度为0或1

此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/68068524
更多有关老猫的文章:http://blog.csdn.net/nthack5730


递归程序的设计思路

一、递归定义

根据上面回文串定义中不难得出设计判断的递归方法的思路:

  • 设计一个返回boolean值的方法,如:check(String str)
  • 方法参数中传入一个字符串参数,作为需要判断的字符串;
  • 将剩下的字符串(子串)作为参数,递归调用自身进行判断

可得出基本的递归代码:【该片段还未加入递归终止条件】

public static boolean check( String str ){
  //doSomeThing
  return check( str.substring( 1, str.length() - 1 ) );//切割两端,将子串递归调用
}

二、终止条件

  1. 对该字符串的首字母和末尾字母进行判断:charAt(0)、charAt(str.length() - 1);
    如果两端字符串不相等,则直接终止递归,返回false
if( str.charAt(0) != str.charAt(str.length()-1) ){
return false;
}
  1. 根据回文串定义,当所有的两端字符都对称相等并且剩下的字符串长度为0或者1,那么这个字符串才是回文串,不难得出递归程序中的终止条件:
if( str.length() <= 1){
return ture;
}

三、最终代码

结合上面的【程序定义】,不难得出最终代码:


public static boolean check(String str) {
  if ( str.charAt(0) != str.charAt(str.length() - 1) ) {
  return false;
  }

  if (str.length() <= 1) {
  return true;
  }
//可改成if...else if....else

  return check(str.substring(1, str.length() - 1));//切割两端,将子串递归调用

}

此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/68068524
更多有关老猫的文章:http://blog.csdn.net/nthack5730


递归辅助方法

一、递归辅助方法出现的原因

  • 看到上面序代码,不少的朋友就会发现,每次的递归调用都是通过【str.substring(int begin, int end)】来获得子字符串并递归调用。
  • 大家都知道String在系统中是静态的,substring(int, int)返回的是新的字符串(子串)。
  • 当原字符串很长的时候,会产生N多子串,这种做法会消耗非常大的内存空间,而且每次都要进行str.substring(int, int)效率也不高。

二、简单说明递归辅助方法

要解决上面出现的问题可以使用递归辅助方法来处理,
通俗来说,递归辅助方法就是通过方法的重载,给方法设定不同的参数,使在调用的时候通过重载达到我们的需要。

在递归程序设计中定义第二个方法来接收附加的参数是一种常用的设计技巧!
辅助方法在设计数组和字符串问题的递归方案上是非常有用的。

三、使用递归辅助方法求解上面的问题

不难看出,在上面的问题中:
* 都是从需要判断的字符串中获取两端的字符进行对比;
* 并且在每次迭代的过程中下标不断向中间靠拢,最终在剩余1个或0个字符的时候返回true【如果过程中两端字符有不相等的马上返回false】;

1.辅助方法具体设计:

  • 我们知道可以通过str.charAt(int)方法来获取对应在字符串下标的字符。
  • 那么就可以设计一个递归辅助方法,传入字符串、一个左边下标的整形参数、一个右边下标的整形参数。
  • 通过这两个下标参数获取对应的字符串

2.运用重载:

加入一个方法进行重载这个重载的方法参数只有一个,作为调用上面设计的三个参数方法的入口,主程序调用这个方法即可;

最终代码如下:

public static boolean newCheck( String str ){
  //重载调用,并且左边参数从下标0开始,右边参数从字符串尾端的位置开始
  return newCheck( str, 0, str.length()-1 );
}

public static boolean newCheck( String str, int beginIndex, int tailIndex ){
  if( tailIndex <= beginIndex ){
  //如果到达中心点,表明前面的所有字符都两端相等,那么就返回true
  return true;
  } else if( str.charAt( beginIndex ) != str.charAt( tailIndex ) ){
  //如果有字符串不相等,那么就返回false
  return false;
  } else{
  //否则,表明并没有到达中心点,但这次下标的两个字符相等,继续判断下一个
  //左边下标指向后移,右边下标指向前移
  return newCheck( str, beginIndex+1, tailIndex-1 );
  }
}

在递归程序设计中定义第二个方法来接收附加的参数是一种常用的设计技巧!
辅助方法在设计数组和字符串问题的递归方案上是非常有用的。


题外话:再简单优化

在这两种方案的代码中,都能够发现一个问题:

当字符串长度为1或者0的时候,程序返回true

处理的方法很简单:

递归调用入口的时候做一个判断检查,就可以解决这个问题!

//一定只能在递归第一个入口处调用,否则方案一直接出错,方案二消耗增加!
if( str.length() <=1 ){
  return false;
}

此文老猫原创,转载请加本文连接:http://blog.csdn.net/nthack5730/article/details/68068524
更多有关老猫的文章:http://blog.csdn.net/nthack5730


猜你喜欢

转载自blog.csdn.net/nthack5730/article/details/68068524
今日推荐