经典递归问题


一、理解递归的过程

使用递归的终止条件:一定要有一个终止条件,否则方法会在栈中持续开辟空间,直到栈内存空间用完,然后引发栈溢出错误(java.lang.StackOverflowError)

递归的过程可以分为两步:

  ①递的过程:在方法的执行过程中会调用本身的方法,这个过程称为递的过程。

  ②归的过程:在遇到终止条件之后,方法会带有返回值返回至上一步进行没有完成的计算。


例:简单理解递归过程

public class Test {
    public static void main(String[] args) {
        int num = 1234;
        print(num);
    }

    public static void print(int n) {
        if (n <= 9) {
            System.out.println(n);
            return;
        }
        print(n / 10);
        System.out.println(n % 10);
    }
}

输出结果

1
2
3
4

  解析:首先主方法调用print()方法并传入参数1234,判断是否符合终止条件,若符合则输出n的值,并结束调用,返回上一层调用继续执行,这是归的过程。遇到自身调用自身方法后开辟新的栈内存等待返回值。

在这里插入图片描述



二、斐波那锲数列

  斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列递推公式为:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)。


例:使用递归方式实现斐波那锲数列的计算

public class Test {
    public static void main(String[] args) {
        int result = fib(5);
        System.out.println(result);
    }
    public static int fib(int n){
        if(n == 1 || n == 2){
            return 1;
        }
        return fib(n - 1) + fib(n - 2);
    }
}

输出结果

5

  说明:斐波那锲数列比较适合于理解递归的方法,但是并不是最好的实现斐波那锲数列的方法。



三、青蛙跳台阶

  问题描述:一只青蛙一次可以跳上1个台阶,也可以跳上两个台阶。求该青蛙跳上n个台阶总共有多少种跳法?

  分析问题:当只有一个台阶时,青蛙只有1种跳法;两个台阶时,青蛙有2种跳法;三个台阶时,青蛙有3种跳法;四个台阶时,青蛙有5种跳法;五个台阶时,青蛙有8种跳法… …

  这时我们可以发现这个问题就是将斐波那锲数列以另一种问题被提出来,分析完问题后可以写如下代码:

import java.util.Scanner;

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入台阶数量:");
        int num = sc.nextInt();//由用户输入整型数字
        System.out.println("总共有跳法" + jumpFloor(num) + "种");
    }

    public static int jumpFloor(int n) {
        if (n == 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        return jumpFloor(n - 1) + jumpFloor(n - 2);
    }
}

输出结果

请输入台阶数量:10
总共有跳法89种



四、汉诺塔问题

  汉诺塔(Hanni Tower),又称为河内塔,源于印度一个古老的传说。大梵天创造世界的时候做了三个金刚石柱子,在一根柱子上从下往上按照大小顺序放着64个黄金圆盘。大梵天命令婆罗门把圆盘从下面楷书按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能方大圆盘,且在三根柱子之间一次只能移动一个圆盘。问该怎么操作?

  分析:假设有A,B,C三个柱子,先需要将A柱子上的圆盘移动到C柱子上,B柱子做辅助。若只有一个圆盘的时候,只需要将圆盘这样移动:A - > C;若是有两个圆盘则需要移动:A -> B,A - > C,B - > C;若是由三个盘子则可以:A - > C,A - > B,C - > B,A - > C,B - > A,B - > C,A - > C移动;… … 若有n个盘子,则将(n-1)个盘子当做一个整体从A柱经过C柱的帮助移动到B柱上,最后一个盘子直接移动到C柱上,再继续讲(n - 1)个盘子从B柱经过A柱的帮助移动到C柱上。

  经过上述的分析可以使用递归的方式实现汉诺塔,如下代码示例:

public class Test {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = sc.nextInt();
        char charA = 'A';
        char charB = 'B';
        char charC = 'C';
        hanio(num, charA, charB, charC);
    }
    //求具体的实现方式,即每一步的走法
    public static void hanio(int n,char a,char b,char c){
        if(n == 1){
            System.out.println(n + "号:" + a + "->" + c);
        }else{
            hanio((n - 1), a, c, b);
            System.out.println(n + "号:" + a + "->" + c);
            hanio((n - 1), b, a, c);
        }
    }
}

输出结果

3       //(这个“3”表示用户输入,确定初始的柱子上的圆盘个数)
1号:A->C
2号:A->B
1号:C->B
3号:A->C
1号:B->A
2号:B->C
1号:A->C

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值