递归算法讲解2

前情提要

上一篇递归算法讲解在这里
递归算法讲解(结合内存图)

没看过的小伙伴可以进去瞅一眼,谢谢!

递归算法的重要性

递归算法是非常重要的,如果想要进大厂,以递归算法为基础的动态规划是必考的,所以我们一定要好好学习递归算法!

本篇博客继续讲解一些递归的经典demo

demo01

递归实现求int类型的数组arr中前n项和,其中arr.length>=n,并且arr当中的元素总和在[-2147483648, 2147483647]之间

还记得递归三步走吗,我们来回顾一下

1. 明确递归的参数和返回值

很显然递归的参数有两个:数组arr + 要求和的序列长度n;
递归的返回值是我们求得的和,不会超过int类型的取值范围,所以数组求和很明显还是int

2. 明确递归的终止条件

我们已知的部分当中,n最小的情况就是递归的终止条件

我们目前已知的,sum(1)肯定是知道的,等于arr[0];sum(2)也是知道的,等于arr[0]+arr[1];

1比较小,所以n==1就是递归的终止条件

递归就是循环,递归的终止条件就是循环的中止条件

还有一些诸如i==j,i>j,都可能称为递归中止条件

3. 明确递归的单层递归逻辑

递归的单层递归逻辑是最难想到的

其实明确单层递归逻辑,很像是中学数学中,让我们求数列的通项公式,我们需要找规律

假设arr = {3,4,7,1,8,12,47……}

sum(1) = 3,sum(2) = 7,sum(3) = 14,sum(4) = 15……

那么sum(n) = ?

差不多是这样的一个过程

当然,本题目是比较简单的,一眼就能看出来,sum(n) = sum(n-1) + arr[n - 1]

递归难就难在,我们很多时候看不出来这个递归逻辑,此时就需要罗列出来找规律

从结束到开始,从部分到整体,从具象到抽象……

代码

	public static void main(String[] args) {
        int[] arr = {3, 4, 7, 1, 8, 12, 47};
        System.out.println(sum(arr, 5));
    }
    
	// 返回类型是int, 参数类型是arr和n
	public static int sum(int[] arr, int n) {
        // 前0项和显然是0
        if (n == 0) {
            return 0;
        }
        // 递归终止条件,返回arr[0]
        if (n == 1) {
            return arr[0];
        }
        // 单层递归逻辑,需要注意要加上arr[n-1]而不是arr[n],因为数组的下标是[0, arr.length - 1]
        return sum(arr, n - 1) + arr[n - 1];
    }

输出结果

在这里插入图片描述

demo02

递归实现折半查找

1. 明确递归的参数和返回值

递归参数是数组arr和要查找的值val

以及left,mid,right三个arr下标,用于判断后的移动

返回类型,可以返回找到的数值的下标(int),也可以什么都不返回(void)

2. 明确递归的终止条件

很明显是arr[i] = val,但是我们用谁去充当这个i指针呢?

熟悉折半查找的同学都知道,折半查找需要至少3个指针:left,mid,right

每一个指针都有可能在移动过程中直接指向val,我们应该选择谁当指针i呢?

很明显是mid,mid可以代表所有情况,left和right就不一定,而且可能陷入死循环

比如arr[mid]正好指向val,但是arr[left] != val,那么就会出现,arr[mid]既不大于val,也不小于

mid,但是无法跳出while循环的情况,也就是死循环

3. 明确递归的单层递归逻辑

当arr[mid] != val时执行递归

如果arr[mid]>val,说明val在mid左边,递归到左区间寻找;

如果arr[mid]<val,说明val在mid右边,递归到右区间寻找。

代码

public static void main(String[] args) {
        // 折半查找的前提是数组有序
        int[] arr = {1, 4, 34, 51, 432, 1111, 2776};

        halfSearch(arr, 4, 0, 3, arr.length - 1);

    }

    public static void halfSearch(int[] arr, int val, int left, int mid, int right) {
        if (val == arr[mid]) {
            System.out.println(val + "找到了,下标是:" + mid);
            return;        }

        if (val > arr[mid]) {
            halfSearch(arr, val, mid, (right + mid) / 2, right);// mid + 1也行
        } else if (val < arr[mid]) {// else即可
            halfSearch(arr, val, left, (mid + left) / 2, mid);// mid - 1也行
        }

    }

在这里插入图片描述

此时就会有聪明的小伙伴问了,如果没找到呢,你这种写法会栈溢出啊

其实我们只需要给left和right加一个判断就可以了

    public static void main(String[] args) {
        // 折半查找的前提是数组有序
        int[] arr = {1, 4, 34, 51, 432, 1111, 2776};

        halfSearch(arr, 432, 0, 3);

    }

    public static int halfSearch(int[] arr, int val, int left, int right) {
        int mid = (left + right) / 2;
        if (val == arr[mid]) {
            System.out.println(val + "找到了,下标是:" + mid);
            return mid;
        }
        if (left <= right) {
            if (val > arr[mid]) {
                return halfSearch(arr, val, mid + 1, right);// mid + 1也行
            } else {// else即可
                return halfSearch(arr, val, left, mid - 1);// mid - 1也行
            }
        } else {
            System.out.println(val + "没找到!");
            return -1;
        }

    }

如果left都大于right了,arr[mid]还是不等于val,那就说明真的没有这个值

demo03

二叉树的中序遍历

左,根,右---------------->中序遍历

如果一个要访问的结点,存在左子树,那么先访问左子树的最左结点

1. 明确递归的参数和返回值

递归参数是二叉树TreeNode,我们叫它root

返回类型,void即可,我们在遍历途中打印每一个结点的val值即可

2. 明确递归的终止条件

root不断遍历,只要不是空,就可以一直遍历

3. 明确递归的单层递归逻辑

在这里插入图片描述

上图这棵树,中序遍历的结果是7,37,13,46,3,19,76,48

因为树是链式结构,我们要遍历一棵树,只能先从根节点开始遍历,不能跨越访问,只能root.left.left……这样访问,这样就令很多同学犯难,我要怎么先从7开始访问呢?

这里其实非常简单,不要想的太复杂

我们仍然先从根节点开始访问,然后访问左子树,最后访问右子树

但是我们在访问左子树结束后再打印,我们只需要保证打印顺序是左根右即可

伪代码(不能运行!!!)

    public static void middle(TreeNode root) {
        if (root == null) {
            return;
        }
        
        // root不是null,先判断左孩子是不是null,再判断右孩子是不是null
        middle(root.left);
        System.out.println(left.val);
        middle(root.right);
        

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/516371.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于单片机的无线红外报警系统

**单片机设计介绍&#xff0c;基于单片机的无线红外报警系统 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的无线红外报警系统是一种结合了单片机控制技术和无线红外传感技术的安防系统。该系统通过无线红外传感器实…

思通数科:利用开源AI能力引擎平台打造企业智能搜索系统

在信息爆炸的时代&#xff0c;如何高效地管理和检索海量数据已成为企业和个人面临的一大挑战。思通数科 StoneDT 多模态AI能力引擎平台&#xff0c;以其强大的自然语言处理&#xff08;NLP&#xff09;、OCR识别、图像识别和文本抽取技术&#xff0c;为用户带来了前所未有的智能…

UE4 C++获取Niagara变量值

UE4 获取Niagara变量值 Niagara有一堆Get方法&#xff0c;但是是基于数据的&#xff0c;单独的Set方法是有的&#xff0c;因此&#xff0c;我们这参考Set源码去Get 源代码如下&#xff1a; 我们的实现&#xff08;当然要返回其他类型值&#xff0c;修改一下对应传参就行了…

一个简单的Demo展示fastapi+tortoise-orm+celery如何搭配

1. 创建并激活虚拟环境 python3 -m venv venv source venv/*/activate 2. 安装依赖包 pip install fastapi uvicorn[standard] tortoise-orm celery[redis] fastapi-cdn-host 3. 配置数据库连接参数 - config.py from typing import TypedDictclass TortoiseInitParam(Ty…

【C语言】翻译环境与运行环境

一、前言 在我们学习C语言的时候&#xff0c;第一个接触的程序就是&#xff1a;在屏幕上打印” hello word! “&#xff0c;可当时的我们却未去深入的理解与感悟&#xff0c;一个程序代码是如何运行的&#xff1b;而这一期的博客&#xff0c;则是带着我们&#xff0c;通过C代码…

【旅行商问题TSP】基于大邻域搜索算法LNS

课题名称&#xff1a;大规模邻域搜索算法LNS求解TSP问题 版本时间&#xff1a;2024-04-01 程序运行&#xff1a;直接运行LNS_TSP.m 文件即可 代码获取方式&#xff1a; QQ&#xff1a;491052175 VX&#xff1a;Matlab_Lover 模型介绍&#xff1a; 第一步&#xff1a;设定…

LeetCode-统计完全连通分量的数量

题目要求&#xff1a; 给你一个整数 n 。现有一个包含 n 个顶点的 无向 图&#xff0c;顶点按从 0 到 n - 1 编号。给你一个二维整数数组 edges 其中 edges[i] [ai, bi] 表示顶点 ai 和 bi 之间存在一条 无向 边。 返回图中 完全连通分量 的数量。 如果在子图中任意两个顶点…

OPPO云VPC网络实践

1 OPPO 云网络现状 随着OPPO业务的快速发展&#xff0c;OPPO云规模增长迅速。大规模虚拟实例的弹性伸缩、低延时需求对网络提出了诸多挑战。原有基于VLAN搭建的私有网络无法解决这些问题&#xff0c;给网络运维和业务的快速上线带来了挑战。 梳理存在的主要问题如下&#xf…

Tik Tok与抖音:一母同胞的不同风采

随着智能手机的普及和网络技术的飞速发展&#xff0c;短视频平台已经成为了大众娱乐生活中不可或缺的一部分。在众多的短视频平台中&#xff0c;Tik Tok和抖音无疑是最受欢迎的两个。尽管它们有着相似的基因——都源自中国&#xff0c;但两者在定位、内容、用户群体以及运营策略…

解决VScode中matplotlib图像中文显示问题

一、更改配置文件 参考这个文件路径找到自己Python环境下的matplotlibrc文件并用记事本打开。 用ctrl F寻找下面的这两行并将前面的#删除&#xff0c;保存并退出。 font.family: sans-serif font.serif: DejaVu Serif, Bitstream Vera Serif, Computer Modern Roman, N…

红黑树介绍与模拟实现(insert+颜色调整精美图示超详解哦)

红黑树 引言红黑树的介绍实现结点类insert搜索插入位置插入调整当parent为gparent的左子结点当parent为gparent的右子结点 参考源码测试红黑树是否合格总结 引言 在上一篇文章中我们认识了高度平衡的平衡二叉树AVL树&#xff1a;戳我看AVL树详解哦 &#xff08;关于旋转调整的…

springboot 项目整合easy-captcha验证码功能

效果 1、验证码使用easy-captcha,在pom文件增加依赖 <!-- google 验证码 --><dependency><groupId>com.github.whvcse</groupId><artifactId>easy-captcha</artifactId></dependency> 2、增加获取kaptcha的ctrl package com.*.*.s…

AcWing 786. 第k个数——算法基础课题解

AcWing 786. 第k个数 文章目录 题目描述思路CGo 题目描述 给定一个长度为 n的整数数列&#xff0c;以及一个整数 k&#xff0c;请用快速选择算法求出数列从小到大排序后的第 k 个数。 输入格式 第一行包含两个整数 n 和 k。 第二行包含 n 个整数&#xff08;所有整数均在 …

韩顺平 | 零基础快速学Python

环境准备 开发工具&#xff1a;IDLE、Pycharm、Sublime Text、Eric 、文本编辑器&#xff08;记事本/editplus/notepad&#xff09; Python特点&#xff1a;既支持面向过程OOP、也支持面向对象编程&#xff1b;具有解释性&#xff0c;不需要编程二进制代码&#xff0c;可以直…

MySQL 导入库/建表时/出现乱码

问题描述&#xff1a; 新建不久的项目在使用Navicat for MySQL进行查看数据&#xff0c;发现表中注释的部分乱码&#xff0c;但是项目中获取的数据使用不会。 猜测因为是数据库编码和项目中使用的不一样&#xff0c;又因为项目的连接语句定义了需要编码&#xff0c;故项目运行…

特征融合篇 | 结合内容引导注意力 DEA-Net 思想 实现双主干特征融合新方法 | IEEE TIP 2024

本篇改进已集成到 YOLOv8-Magic 框架。 摘要—单幅图像去雾是一个具有挑战性的不适定问题,它从观察到的雾化图像中估计潜在的无雾图像。一些现有的基于深度学习的方法致力于通过增加卷积的深度或宽度来改善模型性能。卷积神经网络(CNN)结构的学习能力仍然未被充分探索。本文…

AI大模型与网球运动结合的应用场景及案例分析

AI大模型与网球运动结合的未来前景是广阔的&#xff0c;它不仅能够提升运动员的训练和比赛表现&#xff0c;还能改善教练的策略制定、增强观众的观赛体验以及优化网球赛事的管理。以下是几个具体的应用场景&#xff1a; 1. 运动员技能和表现分析 AI大模型可以通过分析高速摄像…

8.list容器的使用

文章目录 list容器1.构造函数代码工程运行结果 2.赋值和交换代码工程运行结果 3.大小操作代码工程运行结果 4.插入和删除代码工程运行结果 5.数据存取工程代码运行结果 6.反转和排序代码工程运行结果 list容器 1.构造函数 /*1.默认构造-无参构造*/ /*2.通过区间的方式进行构造…

FPGA实现CLAHE算法(Verilog)

在介绍CLAHE算法之前必须要先提一下直方图均衡化&#xff0c;直方图均衡化算法是一种常见的图像增强算法&#xff0c;可以让像素的亮度分配的更加均匀从而获得一个比较好的观察效果。 左边是原图&#xff0c;右边是经过直方图均衡化后图&#xff0c;可以看到肋骨什么的可以更…

鸿蒙应用开发-ArkUI 计算器

一、效果图 在正式介绍ArkUI计算器应用之前&#xff0c;我们先来一睹其风采。效果图上的计算器界面简洁大方&#xff0c;每个按钮都经过精心设计&#xff0c;颜色搭配恰到好处&#xff0c;使得整体界面既美观又实用。数字、运算符等按钮排列整齐&#xff0c;用户可以一目了然地…