ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一。你可以从这里查看全部的Java面试系列。

Q.请写一段代码来计算给定文本内字符“A”的个数。分别用迭代和递归两种方式。

A.假设给定文本为”AAA rating”。迭代方式就很直观,如下:

 public class Iteration {     

     public int countA(String input) {
if (input == null || input.length( ) == 0) {
return 0;
} int count = 0;
for (int i = 0; i < input.length( ); i++) {
if(input.substring(i, i+1).equals("A")){
count++;
}
}
return count;
} public static void main(String[ ] args) {
System.out.println(new Iteration( ).countA("AAA rating")); // Ans.3
}
}

接下来,递归方式的代码如下:

 public class RecursiveCall {
public int countA(String input) {
// exit condition – recursive calls must have an exit condition
if (input == null || input.length( ) == 0) {
return 0;
} int count = 0; //check first character of the input if (input.substring(0, 1).equals("A")) {
count = 1;
} //recursive call to evaluate rest of the input
//(i.e. 2nd character onwards)
return count + countA(input.substring(1));
} public static void main(String[ ] args) {
System.out.println(new RecursiveCall( ).countA("AAA rating")); // Ans. 3
}
}

递归比较难以理解,我们用下面的图来进行说明。

Q.理解递归需要了解哪些概念?

A. 可重入方法(re-entrant method)是可以安全进入的方法,即使同一个方法正在被执行,深入到同一个线程的调用栈里面也不会影响此次执行的安全性。一个非可重入方法则不是可以安全进入的。例如,加入写文件或者向文件中写入日志的方法不是可重入方法时,有可能会毁坏那个文件。

如果一个方法调用了其自身的话,我们称之为递归调用。假定栈空间足够的话,尽管递归调用比较难以调试,在Java语言中实现递归调用也是完全可行的。递归方法是众多算法中替代循环的一个不错选择。所有的递归方法都是可重入的,但是不是所有可重入的方法都是递归的。

栈遵守LIFO(Last In First Out)规则,因此递归调用方法能够记住“调用者”并且知道此轮执行结束之返回至当初的被调用位置。递归利用系统栈来存储方法调用的返回地址。 Java是一种基于栈设计的编程语言。

顺着这个思路还有那些问题可以用来面试?

Q.什么情况下应该采用递归?

A. 上面的例子中其实不必采用递归,循环的方式可以达到目的,但是在某些情况下采用递归方式则代码会更加简短易读。递归方法在循环树结构以及避免丑陋的嵌套循环的情况下是非常好用的。

Q.什么是尾递归,为什么需要尾递归?上面的代码用尾递归方式如何重写?

A. 常规递归方法(亦称,头递归)在上面演示了,这种方式会增加调用栈的大小。每次递归,其入口需要被记录在栈中。方法返回之前需要给countA(input.substring(1)的结果加一个count。假定count大于1,那么返回结果就是count + countA(input.substring(1)),当然事先要算出来countA(input.substring(1))才行。同时,这也意味着直到countA(input.substring(1)计算出来才能得到最终的结果。因此,最后需要做的事其实是加法运算,而非递归本身。

尾递归的好处是什么?

在尾递归中,最后要做的是递归,加法运算在之前就已经完成了。一轮递归调用完毕后就没有其他事情了(除了加法运算),因此调用时生成的信息也就没什么用了。这些无用信息可以丢弃,然后用一组新的参数来调用一次递归方法来产生一个新的结果。这也就是说,栈调用减少带来了内存消耗减少并且程序的性能更好。

尾递归重写的代码如下:

 public class TailRecursiveCall {
public int countA(String input) {
// exit condition – recursive calls must have an exit condition
if (input == null || input.length() == 0) {
return 0;
} return countA(input, 0) ;
} public int countA(String input, int count) {
if (input.length() == 0) {
return count;
} // check first character of the input if (input.substring(0, 1).equals("A")) {
count = count + 1;
} // recursive call is the last call as the count is cumulative return countA(input.substring(1), count);
} public static void main(String[] args) {
System.out.println(new TailRecursiveCall().countA("AAA rating"));
}
}

扩展阅读:

-- 扫描加关注,微信号: importnew --

英文原文: Java Success,编译:ImportNew - 郑雯

译文链接:http://www.importnew.com/2329.html

【如需转载,请在正文中标注并保留原文链接、译文链接和译者等信息,谢谢合作!】

【转】常见Java面试题 – 第四部分:迭代(iteration)和递归(recursion)的更多相关文章

  1. 【转】常见Java面试题 – 第三部分:重载(overloading)与重写(overriding)

    ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一.你可以从这里查看全部的Java面试系列. 这篇文章介绍的常见面试题是关于重载(overloading)方法和重写( ...

  2. 【转】常见Java面试题 – 第二部分:equals与==

    ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一.你可以从这里查看全部的Java面试系列. Q2.下面的代码片段的输出是什么? Object s1 = new St ...

  3. 【转】常见Java面试题 – 第一部分:非可变性(Immutability)和对象引用(Object reference)

    ImportNew注: 本文是ImportNew编译整理的Java面试题系列文章之一.请看此系列相关面试题.你可以从这里查看全部的Java面试系列. 一些比较核心的Java问题经常会用来考验面试者的J ...

  4. 【面试必备】常见Java面试题大综合

    一.Java基础 1.Arrays.sort实现原理和Collections.sort实现原理答:Collections.sort方法底层会调用Arrays.sort方法,底层实现都是TimeSort ...

  5. java面试题汇总四

    第三部分 Java SE基础 3.1 java多线程 3.1.1 线程的实现方式,怎么启动线程怎么区分线程? 1.线程的实现方式: 有 4 种方式可以用来创建线程: 2.继承 Thread 类   2 ...

  6. 转载文章 208 个最常见 Java 面试题全解析

    最近正值春招,一直在给公司招聘 Java 程序员,我从 2015 年做 TeamLeader 开始就习惯性地收集平时遇到的 Java 技术问题或周围朋友见过的面试题,经过不断筛选,终于凝练成一套实用的 ...

  7. BATJ的常见java面试题

    JAVA基础 JAVA中的几种基本数据类型是什么,各自占用多少字节. String类能被继承吗,为什么. 不可以,因为String类有final修饰符,而final修饰的类是不能被继承的,实现细节不允 ...

  8. java零基础之---常见java面试题

    看到别人分享的面试题,感觉蛮全面的,分享出来,慢慢研究答案. 一.Java 基础 1.JDK 和 JRE 有什么区别? 2.== 和 equals 的区别是什么? 3.两个对象的 hashCode() ...

  9. 一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)

    这里是参考B站上的大佬做的面试题笔记.大家也可以去看视频讲解!!! 文章目录 31.线程池复用的原理 32.spring是什么? 33.对Aop的理解 34.对IOC的理解 35.BeanFactor ...

随机推荐

  1. 异常解决:java.lang.IllegalStateException: Failed to introspect Class

    java.lang.IllegalStateException: Failed to introspect Class 异常详情 原因 解决办法 异常详情 Exception encountered ...

  2. rsa加密(非对称加密)

    rsa加密 是非对称加密 需要公钥 与 私钥 这个公钥私钥的具体值需要与后端协商定下 rsa js代码如下 代码太多不插入了 html代码如下 <!DOCTYPE html> <ht ...

  3. 怎样判断一个jquery对象是否为空jquery对象

    if ( $('#myDiv').length ){} http://stackoverflow.com/questions/47... 也可以直接判断$('#myDiv')[0]===undefin ...

  4. H3C NAT Server

  5. phpStudy中升级MySQL版本到5.7.17的方法步骤

    http://www.jb51.net/article/120263.htm 前言 今天在工作发现一个错误,在往本地导数据表的时候老是报错: ? 1 [Err] 1294 - Invalid ON U ...

  6. java声明异常(throws)

    在可能出现异常的方法上声明抛出可能出现异常的类型: 声明的时候尽可能声明具体的异常,方便更好的处理. 当前方法不知道如何处理这种异常,可将该异常交给上一级调用者来处理(非RuntimeExceptio ...

  7. 配置gitignore后使其生效命令

    改动过.gitignore文件之后,在repo的根目录下运行: git rm -r --cached . git add . 之后可以进行提交: git commit -m "fixed u ...

  8. 本地安装配置redis

    Windows中redis的下载及安装.设置   本文是转载自:https://www.cnblogs.com/jylee/p/9844965.html 下载地址: https://github.co ...

  9. 【js】vue 2.5.1 源码学习(二) 策略合并

     一.  整体思路     1 首先是代码的大体构造,先判断引入代码的环境,即对应amd 和cmd的处理     2 vue_init 需要借助 initMinxin    ==>>> ...

  10. H3C生成树的不足