JAVA实现汉诺塔,青蛙跳台阶...

学习递归思想以及一些相关题。

题:阶乘 汉诺塔 青蛙跳台 斐波那契数列 输出数字 递归求 1 + 2 + 3 + ... + 10  返回组成它的数字之和(1234-->1+2+3+4=10)   递归打印1到9的数字

目录

N的阶乘

按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

递归求 1 + 2 + 3 + ... + 10

递归打印1到9的数字

返回组成它的数字之和(1234-->1+2+3+4=10) 

斐波那契数列

汉诺塔

青蛙跳台阶


嵌套:方法里面调用方法;a方法里面调用了b方法或者c方法或者其他方法。
递归:特殊的嵌套,方法里面调用了自己(方法);a方法里面调用了a方法本身;

理解:有点像俄罗斯套娃一样,大的里面不断套小的,但是一整套套娃的类型都是一样的(都是一个模样),递归也是如此。当遇到一个大问题解决不了,可以将它拆分成小问题,而小问题与大问题有相同的解决方案,那么小问题解决后,大问题不就解决了。

必要条件:
        1.已知最小子问题的答案(初始条件),得让递推公式停下来的条件。
        2.能够不断将大问题划分成更小的子问题(有递推公式)

初阶:刚开始做的时候没有太多的思路,先写出他的初始条件,在调用它的方法,然后画图去理解,看哪里不对就去修改,最终改为正确答案。
进阶:已经差不多了,就可以去思考,首先是个大问题,我不断拆成小问题(比如递归求1+...+9的和,那我可以想去思考1+...+8的和,接着可以思考1的和),我还能想到最小子问题的答案(此时初始条件就知道了)。(方法就是最后求解的答案,也就是该问题的答案)

N的阶乘

//n的阶乘
    public static int fac(int n){
        if(n == 1){
            return 1;
        }
        int result = n*fac(n-1);
        return result;
    }

    public static void main(String[] args){
       int ret =  fac(3);
        System.out.println(ret);
    }

按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)

//按顺序打印一个数字的每一位(例如 1234 打印出 1 2 3 4)
    public static void numPrint(int n){
        if(n / 10 == 0){
            System.out.print(n+ " ");//输出最高位
            return ;
        }
        numPrint(n / 10);
        System.out.print(n % 10+" ");
        return ;
    }
    public static void main(String[] args){
        numPrint(1234);
    }

递归求 1 + 2 + 3 + ... + 10

 //递归求 1 + 2 + 3 + ... + 10
    public static int sumFac(int n){
        //问题可以拆成 1+..+9 最小就是当遇到1
        if(n == 1)
            return n;
        int ret = n + sumFac(n - 1);
        return ret;
    }

    public static void main(String[] args) {
        int ret = sumFac(10);
        System.out.println(ret);
    }

有种感觉:本身要求1+...+10,那我可以先写成10+ 剩余的(1+...+9),是不是就拆成小问题了。

递归打印1到9的数字

//递归打印1到9的数字
    public static void printNum(int n){
        //要打印1-9,如何打印1-8...那就得考虑如何打印1
        if(n == 1){
            System.out.print(n+" ");
            return ;
        }
        //从1-9一直到先打印1
        printNum(n - 1);
        System.out.print(n+" ");
        return;
    }

    public static void main(String[] args){
        printNum(9);
    }

返回组成它的数字之和(1234-->1+2+3+4=10) 

思路:
        1.找初始条件:让我求1234组成的数字之和,我得先求123组成的之和,我得求12,得求1,因此我得先找到最高位 当n/10==0 时就是最高位了,我就返回它。
        2.找递推公式:既然是递推,那肯定要用到这个方法,我又知道要让数字1234,变为123,变为12...那我就得让该方法里的数字num/10才能变小。而该方法是返回单个位的值的,拿我需要和上一位相加num % 12,然后就是返回。大概可以这样理解

//返回组成它的数字之和(1234-->1+2+3+4=10)
    public static int numSum(int num){
        //求1234的和 我得先求123 子问题也就是找一位
        if(num / 10 == 0){  //或者if(num < 10)
            return num;//把最高位返回去
        }
        int sum =  num % 10 + numSum(num / 10);//从1234 不断缩小123 12 1 并且和前一位相加
        return  sum;        
    }

    public static void main(String[] args){
        int sum = numSum(1234);
        System.out.println(sum);
    }

斐波那契数列

1 1  2 3 5...每一项等于前两项之和(除了第1和第2项)

//递归求斐波那契数列第n项
    public static int fib(int n) {
        //第n项不会求,我会求第一第二项
        if(n == 1 || n == 2){
            return 1;
        }
        //第n项不就等于第n-1项加上n-2项么
        int num = fib(n - 1) + fib(n - 2);
        return num;
    }
    public static void main(String[] args) {
        int num = fib(6);
        System.out.println(num);
    }

在做斐波那契数列时,不建议使用递归方法,调用了两次该方法,就是两个方法不停地递归,之后可能会有更多的递归,有点像一颗树。而且方法不停的重复计算数据,效率比较低下。就拿fib(1)和fib(2)来说就重复8次,如果求n= 40的fib,重复会更高。

 建议使用循环去实现菲波那切数列

//循环实现fib
    public static int fib(int n) {
        if(n == 1 || n == 2){
            return 1;
        }
        int f1 = 1;
        int f2 = 1;
        int fn = n;
        for(int i = 3; i <= n; ++i){
            fn = f1 + f2;
            f1 = f2;
            f2 = fn;
        }
        return fn;
    }
    public static void main(String[] args) {
        int num = fib(6);
        System.out.println(num);
    }

汉诺塔

把n个盘子借助b从a移到c,现在我不会移动n个过去,那我先移动一个过去

//汉诺塔问题
    //n代表盘子数,意思是把n个盘子从a柱子借助b柱子移动到c柱子
    public static void hanno(int n,char A,char B,char C){
        if(1 == n){
            System.out.println(A+"-->"+C);
            return ;
        }
        hanno(n-1,A,C,B);
        System.out.println(A+"-->"+C);
        hanno(n-1,B,A,C);
    }
    public static void main(String[] args){
        hanno(3,'A','B','C');
    }

当一个盘子直接从a移到c,当n个盘子,那我就先从把n-1个盘子从a借助b移到c,再把剩下的一个从a移到c,最后把n-1个盘子从b借助a移到c。
刚开始学的时候,总想着去一步一步看看里面是怎么写的,就导致我当初学的时候很困难,但可以画图解释清楚,这次做了一些关于递归的题让我对递归有了另外一种认识:
1.找初始条件
2.理清楚原问题和拆分问题的关系从而建立递推关系

找到一篇比较好的文章,看完后绝对有更深的理解:C语言 - 汉诺塔详解(超详细)_wh128341的博客-CSDN博客_c语言汉诺塔

青蛙跳台阶

一只青蛙可以一次跳 1 级台阶或一次跳 2 级台阶。试问跳n级台阶有多少种跳法。
这篇文章也是深刻讲解,可以去看看。
详解青蛙跳台阶的递归问题_Pinksatrfish的博客-CSDN博客_青蛙跳台阶递归

//一只青蛙可以一次跳 1 级台阶或一次跳 2 级台阶
    public static int step(int n){//跳n层台阶有step(n)种结果
        if(1 == n){
            return 1;
        }
        if(2 == n){
            return 2;//每次跳一级或一次跳两级
        }
        //其余的情况都可以用前两种推出来
        //n层台阶的方法为: n-1层台阶的方法+ n-2 层台阶的方法。
        int sum = step(n - 1) + step(n - 2);
        return sum;
    }

    public static void main(String[] args) {
        int sum = step(4);
        System.out.println(sum);
    }

刚开始做的时候大家都想着如何去把代码一步一步走下去,那就试着画多个方法图然后去理解,等做到斐波那契、汉诺塔时,大家就会想着将原问题拆为一个小问题+部分去解决


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值