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面试题——方法的递归与迭代的主要内容,如果未能解决你的问题,请参考以下文章

JavaSE 方法的使用

面试题10:斐波那契数列

JavaSE面试题——方法的参数传递机制

JavaSE相关面试题

每日算法&面试题,大厂特训二十八天——第七天(递归|回溯|迭代)

经典面试题二二叉树的递归与非递归遍历(前序中序后序)