递归介绍及练习

本文详细介绍了递归算法的概念,通过求和、阶乘、斐波那契数列和汉诺塔等问题的递归解法,展示了如何将复杂问题分解为子问题并逐步求解。最后以小白上楼梯问题为例,进一步说明递归的应用和思维过程。
摘要由CSDN通过智能技术生成

递归是一种重要的算法,在一些竞赛中,很多问题如果没有特别好的想法时,都可以用递归来求解。
所谓递归,它是指一个函数直接或间接地调用自身来解决问题。递归的基本思想是将一个复杂的问题分解为若干个简单的子问题,然后逐个解决这些子问题,最终达到解决整个问题的目的。

通俗点来讲呢,比如说刚开学,你不知道校长在哪,就去问另一个同学,他也不知道,他就再去问另一个同学,就这样一直循环,终于有个同学知道,他就把答案告诉上一个同学,最终,这个答案顺着这个链条给到了你。
大概就是这么个意思,每一层递归都是带着问题去找答案,而原始答案就是递归的出口,在实际的问题中需要去找到每一层之间的规律,将原始答案通过规律,一步一步计算,最终得到所要的值。

在这里插入图片描述
通过递归来做题,最关键的就是找出子问题,找出递归的出口,递归一定是要有出口的,不然函数一直在调用,就会导致内存溢出。

我们还是先通过简单的例题来理解具体的思路:

在这里插入图片描述
这里呢,我们需要去求1~100之间的和,那么就可以逐步的去转化为求 1 ~ 99之间的和,1 ~ 98……1 ~ 2 ,以及为1的时候的情况,也就是递归的出口。

//使用递归的方法求1~100的和
    public static int getsum(int number) {
        if (number == 1) {
            return 1;
        }
        //当前数字加上前面 number - 1 个数字的和
        return number + getsum(number - 1);
    }

明白了这道题之后,那么通过递归求阶乘也是一样的道理了,我们用代码实现以下:

 public static int getFactorialRecursion(int number) {
        if (number == 1) {
            return 1;
        }
        //转化为当前数字乘以前 number - 1 的数字的阶乘
        return number * getFactorialRecursion(number - 1);
    }

方法名起这么长只是为了高级,哈哈哈

接下来我们来看一个很经典的问题——斐波那契数列
在这里插入图片描述
我们都知道,斐波那契数列就是第n项等于前两项的和,通项公式也就是
f (n) = f (n - 1) + f (n - 2)
在这里插入图片描述

知道这个就好办了,接下来我们看怎么去用递归去求解

public static int fibonacci(int n) {
        //第一项和第二项都是 1 
        if (n == 1 || n == 2) {
            return 1;
        }
        //求第 n 项就是求 第(n-1)和第(n-2)项的和
        else {
            return fibonacci(n - 1) + fibonacci(n - 2);
        }
    }

之前的一篇文章中有关于斐波那契数列的两种解决方式,感兴趣的话可以看一下 : 通过递归和迭代两种方式实现斐波那契数列

接下来我们讲一下汉诺塔的问题,每次只能移动一个盘子,而且必须保证大的盘子在小的盘子下面,将初始状态下的 A 柱上的盘子都移动到 C 盘
在这里插入图片描述
当 n 为 1的时候,没什么好说的,直接放就完事了

盘子的数量大于 1 时,把除了最下面的盘子看作一个整体,以 C 为辅助塔,移动到目标塔 B ,再将蓝色的盘子放入C,此时最大的蓝色盘子正确归位,每次放置时,这三个柱子谁是开始塔,目标塔,辅助塔都是在不断变化的,这个需要仔细去思考明白。
在这里插入图片描述
最后呢将B柱看作一个整体,借助 A 柱,将 B 柱上的盘子放到 C 柱。
在这里插入图片描述
完整的代码就是:

public class HanoiTower {
    public static void main(String[] args) {
        printHanoiTower(3,"A","B","C");
    }
    //frome:起始塔 temp: 辅助塔  goal: 目标塔
    public static void printHanoiTower(int N,String from,String temp,String goal){
        if(N == 1){
            System.out.println("移动" + N + "从" + from + "到" + goal);
            return;
        }else{
            //转化为从N - 1整体开始移动,此时goal为辅助塔,temp为目标塔对应上面图片的 A, B, C
            printHanoiTower(N - 1,from,goal,temp);
            //N可以到达目标柱子
            System.out.println("移动" + N + "从" + from + "到" + goal);
            //N-1整体所在的其实位置是原来的temp塔,以from为辅助塔,移动到目标塔
            printHanoiTower(N - 1,temp,from,goal);
        }
    }
}

运行结果呢也和实际操作一致在这里插入图片描述

递归的代码其实都比较简洁,但其中的思维还是有点难的,我自己学习这个汉诺塔的问题时看了好几个博主的视频才整明白,用动画的话比较直观一点。

最后呢再来一道小白上楼梯的题

在这里插入图片描述
没想到吧,这也可以用递归来解决,如果不用递归的话,其实我也想不到该去怎么去做,那接下来我们分析一下这道题:

首先我们假设有 n 级台阶,当他到达n阶之前的一步,可以在第 n - 1级,可以在第 n - 2级,也可以在第 n - 3 级台阶,那么到达第n级台阶的步数就是 f (n - 1) + f( n - 2) + f(n - 3) 加起来
在这里插入图片描述

public static int count(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        //可以一级一级,也可以两级一起
        if (n == 2) {
            return 2;
        }
        //如图,
        if (n == 3) {
            return 4;
        }
        return count(n - 1) + count(n - 2) + count(n - 3);
    }

n = 3时的情况,共有四种方式
在这里插入图片描述
画工不太好,大家凑合着看哈~
那么本次关于递归的分享就到这里了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值