JavaSE面试题——方法的递归与迭代
Posted 张起灵-小哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaSE面试题——方法的递归与迭代相关的知识,希望对你有一定的参考价值。
1.Go!!!
编程题:有n步台阶,每次只能走一步或者走两步,则共有多少种不同的走法?
这个问题了话,我能想到的就是两种方法:1.递归;2.迭代。
这二者的区别在于:方法调用自身称为递归;利用变量的原值推出新值称为迭代。
2.递归
- n=0:没意义,台阶数不可能小于1。
- n=1:只能走一步直接到位,f(1)=1。
- n=2:①1+1;②2;f(2)=2。
- n=3:①1+1+1;②1+2;③2+1;f(3)=3 = f(2) + f(1)。
- n=4:①1+1+1+1;②1+2+1;③1+1+2;④2+1+1;⑤2+2;f(4)=5 = f(3) + f(2)。
- n=5:①1+1+1+1+1;②1+2+1+1;③1+1+2+1;④2+1+1+1;⑤1+1+1+2;⑥1+2+2;⑦2+1+2;⑧2+2+1;f(5)=8 = f(4) + f(3)。
- ......
- n=x:f(x) = f(x-1) + f(x-2)
规律已经可以看出来了,从n=3开始,后面的每一项都等于它对应的前两项之和。
这里想说一下,不要说这个就是斐波那契数列,斐波那契数列的前几项是 0、1、1、2、3、5、8......,你们学过斐波那契数列吗?和这个一样吗???合适的说法还是类似于斐波那契数列。(不要说这就是斐波那契数列,让别人听了误以为真,忽略了斐波那契数列前面还有两项0和1,数学的奇妙之处就在于严谨。你也别扯什么这是计算机不是什么数学,你仔细想想计算机是不是基于数学的?它们二者谁先诞生?)
import java.util.Scanner;
/**
*
*/
public class Step1 {
public static long f(long n) {
if (n < 1) {
throw new IllegalArgumentException("台阶数n不能小于1");
}
if (n == 1 || n == 2) {
return n;
}
return f(n-1) + f(n-2);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long start = System.currentTimeMillis();
long n = scanner.nextLong();
System.out.println(f(n));
long end = System.currentTimeMillis();
System.out.println("程序运行总耗时: " + (end - start));
}
}
3.迭代
这里首先我们需要三个临时变量one、two、result,其中one保存的是最后走一步的情况,two保存的是最后走两步的情况,result是最终的结果。
- n=0:没意义,台阶数不可能小于1。
- n=1:只能走一步直接到位,f(1)=1。
- n=2:①1+1;②2;f(2)=2。
- n=3:①先到达f(1),然后从f(1)直接走两步到达,即此时f(1)=two;②先到达f(2),然后从f(2)直接走一步到达,即此时f(2)=one;所以f(3)=one + two。
- n=4:当n=3时,two表示最后走两步的情况,而当n=4,台阶数多了一阶,这个时候n=3时的那个one(最后走一步)就变成了最后要走两步,即 two = one;
而n=3时的那个one表示最后走一步的情况,此时n=4,台阶数多了一阶,这个时候n=3时的那个result(最终结果)就变成了最后要走一步,即 one = result。
import java.util.Scanner;
/**
*
*/
public class Step2 {
public static long f(long n) {
if (n < 1) {
throw new IllegalArgumentException("台阶数n不能小于1");
}
if (n == 1 || n == 2) {
return n;
}
long one = 2; //初始化为走到第二级台阶的走法(保存最后走一步)
long two = 1; //初始化为走到第一级台阶的走法(保存最后走两步)
long result = 0;
for (long i = 3; i <= n; i++) {
//最后走一步 + 最后走两步的走法
result = one + two;
two = one;
one = result;
}
return result;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long start = System.currentTimeMillis();
long n = scanner.nextLong();
System.out.println(f(n));
long end = System.currentTimeMillis();
System.out.println("程序运行总耗时: " + (end - start));
}
}
最终对比递归和迭代来看:
递归:
- 优点:大问题转化为小问题,可以减少代码量,同时代码精简,可读性好。
- 缺点:递归调用浪费了空间,而且递归太深容易造成堆栈的溢出。
迭代:
- 优点:代码运行效率好,因为时间只因循环次数增加而增加,而且没有额外的空间开销。
- 缺点:代码比递归要复杂,同时可读性不如递归。
以上是关于JavaSE面试题——方法的递归与迭代的主要内容,如果未能解决你的问题,请参考以下文章