算法_递归

本文深入浅出地介绍了递归的概念,将其与循环进行了比较,并通过递归三部曲(终止条件、返回值、本级任务)解析了递归问题的解决步骤。文章通过递归求和、阶乘、斐波那契数列、链表操作等经典例子,展示了递归在算法和数据结构中的应用。同时,还提及了递归在实际项目中如组装三级分类问题中的使用,进一步巩固了递归的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考大佬博客

1.递归的理解

递归就是自己调用自己的一个过程,我们不必去纠结每一级干了什么,我们只需要关注某一级的实现即可,因为每一级都是相同的!!!

递归可以看做是循环的简化版, 递归的本质可以看做就是循环

比如一个方法A,一直调用自己,这时所有的方法会在一个栈中,当某一个满足了终止条件时,最后一次调用的方法即栈顶的方法会执行完毕然后出栈,将结果返回给调用它的方法,即此时的栈顶方法一直下去最终第一个A方法执行完毕栈空,程序结束

在这里插入图片描述

2.递归三部曲

根据上面的递归的理解,总结出解决递归问题的三个步骤

  1. 找整个递归的终止条件:递归应该在什么时候结束?
  2. 找返回值:应该给上一级返回什么信息?
  3. 本级递归应该做什么:在这一级递归中,应该完成什么任务?

3.递归的经典应用

3.1求和

问题:编写一个方法,传入一个整数n 求1到n的和 要求:使用递归

这个问题我们最简单的可以使用for循环,直接加即可

我们使用递归解决这个问题,求1到n的和,也就是n到1的和

  • 第一步-找递归的终止条件,递归最先执行完毕的是最后的操作,即最后会完成n+(n-1),当n=1的时候,这时无需递归,直接返回1即可
  • 第二步-找返回值,我们求n到1的和,肯定希望返回 n+(n-1到1的和)
  • 第三步-本级递归做什么:本级递归就是将n和n-1之前的数相加,然后返回给上一级

就是 每一级做的事就是将n+ n后面的所有数的和 然后返回

n n-1 n-2 ... 1

代码实现

public int sum(int n){
    	//终止条件
        if (n==1){
            return 1;
        //每一级做的事,这个数+他前面的数的和并返回
        }else {
            return n+sum(n-1);
        }
    }

3.2阶乘

传入一个整数n,求n到1的阶乘

跟3.1类似

public int jc(){
    //到1结束
    if(n==1){
        return 1;
       //每一层做的事就是将这一层的数*前面数的乘积返回
    }else{
        return n*jc(n-1);
    }
}

3.3斐波那契数列

给定一个整数n,求斐波那契数列的第n项

斐波那契数列,除前两项外,其余每一项都等于它的前两项的和

0 1 1 2 3 5 8 13 21 ...

三部曲

我们要求第n项,需要求n-1 和 n-2项 。。。。

找终止条件:因为前两项不符合,所以当递归到n=0 或者n=1时直接返回对应的0 或 1即可

返回值即这个方法的作用是什么: 作用就是求第n项的的值

每一级该干什么:每一级应该将这一项的前两项的和加起来返回给上一级

public int fib(int n){
   	if(n==0) return 0;
    if(n==0) return 0;
    //每一级干的事就是将n的前两项的和相加
    else return fib(n-1) + fib(n-2);
}

3.4遍历链表

一般的遍历链表都是循环,这里我们使用递归试一试

找终止条件:当走到null的时候返回

返回值即这个方法的作用是什么:输出每一个节点的值

每一级该干什么:输出这一当前节点的值

    public  void showData2(ListNode head) {
        if (head == null) {
            return;
        }
        System.out.println(head.val);
        showData2(head.next);
    }

3.5反转链表

力扣题解

3.6交换链表中的节点

力扣题解

3.7删除链表中的重复元素

力扣题解

3.7项目应用:组装三级分类

在谷粒商城的项目中的组装三级分类时使用了递归

在这里插入图片描述

模拟三级分类进行组装

定义一个实体,判断一个person实例是不是有父分类,就看它的dadId,如果dadId为0,说明这个实例是以及分类,其他实例的dadId等于某一个实例的id

public class Person {
    
    //主键
    private Integer id;
    
    //父分类id
    private Integer dadId;
    
    //子分类
    private List<Person> sons;

}

代码实现

三部曲

1、终止条件 当到最后一级分类时,他没有子分类,就会终止

2、返回值 :返回值代表某一级分类的下一级分类

3、每一级该干什么:现在有一级分类,先找到它的所有二级分类,然后找到所有二级分类的子分类并设置进去,最后返回这个二级分类

  //创建一些实例,然后使用一个List装起来,
  List<Person> persons = new ArrayList();
  
    @Test
    public void 模拟三级分类() {

        // 先找到所有的一级分类
        List<Person> collect = persons.stream().filter(p -> p.getDadId() == 0).collect(Collectors.toList());

        //遍历所有的一级分类 为每一个一级分类设置上二级分类 二级分类设置上一级分类
        List<Person> collect1 = collect.stream().peek(p -> p.setSons(get(persons, p))).collect(Collectors.toList());

    }

    //递归方法  为一个分类设置上它的所有子分类
    private List<Person> get(List<Person> persons, Person root) {
        //终止条件 当某一个分类没有父分类时结束
        if (root.getDadId() == null) {
            return null;
        }
        //先找到这个节点的所有子分类 即root的所有子分类
        List<Person> tmp = persons.stream().filter(person -> root.getId().equals(person.getDadId())).collect(Collectors.toList());

        //将这个节点的子分类的子分类设置到子分类中
        //即找到root的所有子分类的子分类,并设置到属性中
        List<Person> res = tmp.stream().peek(person -> person.setSons(get(persons, person))).collect(Collectors.toList());
        return res;
    }

3.8快速排序

排序算法

3.9树相关

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shstart7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值