递归算法讲解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和npublic static int sum(int[] arr, int n) {// 前0项和显然是0if (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,再判断右孩子是不是nullmiddle(root.left);System.out.println(left.val);middle(root.right);}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【React】基于JS 3D引擎库实现关系图(图graph)

主角&#xff1a;3D Force-Directed Graph 简介&#xff1a;一个使用ThreeJS/WebGL进行3D渲染的Graph图库 GitHub: https://github.com/vasturiano/3d-force-graph Ps: 较为复杂或节点巨大时&#xff0c;对GPU>CPU消耗较大&#xff0c;同量级节点对比下优于AntV G6和Echarts…

RDD算子(四)、血缘关系、持久化

1. foreach 分布式遍历每一个元素&#xff0c;调用指定函数 val rdd sc.makeRDD(List(1, 2, 3, 4)) rdd.foreach(println) 结果是随机的&#xff0c;因为foreach是在每一个Executor端并发执行&#xff0c;所以顺序是不确定的。如果采集collect之后再调用foreach打印&#xf…

51之定时器与中断系统

目录 1.定时器与中断系统简介 1.1中断系统 1.2定时器 1.2.1定时器简介 1.2.2定时器大致原理及其配置 1.2.3定时器所需的所有配置总介 2.定时器0实现LED闪烁 3.使用软件生成定时器初始化程序 1.定时器与中断系统简介 1.1中断系统 首先&#xff0c;我们需要来了解一下什么…

Vue项目中引入html页面(vue.js中引入echarts数据大屏html [静态非数据传递!] )

在项目原有vue&#xff08;例如首页&#xff09;基础上引入html页面 1、存放位置 vue3原有public文件夹下 我这边是新建一个static文件夹 专门存放要用到的html文件 复制拖拽过来 index为html的首页 2、更改路径引入到vue中 这里用到的是 iframe 方法 不同于vue的 component…

python爬虫获取豆瓣前top250的标题(简单)

今天是简略的一篇&#xff0c;简单小实验 import requests from bs4 import BeautifulSoup# 模拟浏览器的构成&#xff08;请求头&#xff09; headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

从零开始搭建后端信息管理系统(新手小白比如)

如果你是新手小白&#xff0c;首先我们要进行一些准备工作&#xff0c;安装一些基础软件&#xff0c; 备注一下&#xff1a;这里安装的vue环境的后台管理系统&#xff0c;不同的后台管理系统&#xff0c;需要安装不同的插件 准备工作&#xff1a; 安装 Visual Studio Code …

如何使用 Midjourney?2024年最新更新

一&#xff1a;基础篇 1&#xff1a;注册 首先&#xff0c;你需要注册一个 Discord 账号&#xff0c;然后加入 Midjourney 的 Discord 服务器。或者去 Midjourney 的官网点击右下角的 Join the Beta&#xff1a; ​ 2&#xff1a;在 Discord 公共服务器里使用 注册并进入到…

Unix 网络编程, Socket 以及bind(), listen(), accept(), connect(), read()write()五大函数简介

Unix网络编程是针对类Unix操作系统&#xff08;包括Linux、BSD以及其他遵循POSIX标准的操作系统&#xff09;进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中&#xff0c;网络编程通常涉及到以…

kubectl explain资源文档命令

学习并使用了一段时间的kubernetes&#xff0c;发现对k8s还是了解甚少&#xff0c;于是利用上下班通勤的时间又去B站看一些大佬的视频&#xff0c;又来重学巩固一遍知识&#xff0c;并做些记录。 之前在学习使用过程中未成了解过explain这个命令&#xff0c;因为自己部署的版本…

【开发、测试】接口规范与测试

接口测试基础 url 是互联网标准资源地址&#xff0c;称为统一资源定位符 组成&#xff1a;协议&#xff0c;服务器地址&#xff0c;端口号 HTTP协议 HTTP&#xff1a;超文本传输协议&#xff0c;基于请求与响应的应用层协议 作用&#xff1a;规定了客户端和服务器之间的信…

NoSQL之Redis配置

文章目录 NoSQL之Redis配置一、关系数据库和非关系数据库1、关系型数据库2、非关系型数据库3、非关系型数据库产生背景4、关系型数据库和非关系型数据库的区别4.1 数据存储方式不同4.2 扩展方式不同4.3 对事务性的支持不同 5、总结5.1 关系型数据库5.2 非关系型数据库 二、Redi…

Anaconda/Python快速安装jieba 【win/mac】

一、直接上命令 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba 我是在PyCharm里面的终端输进去。 之后就很快速的看到成功的下图。 二、官网 官网下载的速度太慢了——这是官网地址https://pypi.org/project/jieba/#files 点进去之后点击下载&#xff0c…

Star GAN论文解析

论文地址&#xff1a;https://arxiv.org/pdf/1912.01865v1.pdf https://openaccess.thecvf.com/content_cvpr_2018/papers/Choi_StarGAN_Unified_Generative_CVPR_2018_paper.pdf 源码&#xff1a;stargan项目实战及源码解读-CSDN博客 1. 概述 在传统方法中&#x…

练习14 Web [极客大挑战 2019]Upload

phtml格式绕过&#xff0c;burp修改content-type绕过&#xff0c;常见的文件上传存放目录名 题目就叫upload&#xff0c;打开靶机 直接上传一个图片格式的一句话木马&#xff0c;返回如下&#xff1a; 提交练习5和9中的两种可以执行图片格式php代码的文件&#xff0c;修改con…

全面解析找不到msvcr110.dll,无法继续执行代码的解决方法

MSVCR110.dll的丢失可能导致某些应用程序无法启动。当用户试图打开依赖于该特定版本DLL文件的软件时&#xff0c;可能会遭遇“找不到指定模块”的错误提示&#xff0c;使得程序启动进程戛然而止。这种突如其来的故障不仅打断了用户的正常工作流程&#xff0c;也可能导致重要数据…

[中级]软考_软件设计_计算机组成与体系结构_08_输入输出技术

输入输出技术 前言控制方式考点往年真题 前言 输入输出技术就是IO技术 控制方式 程序控制(查询)方式&#xff1a;分为无条件传送和程序查询方式两种。 方法简单&#xff0c;硬件开销小&#xff0c;但I/O能力不高&#xff0c;严重影响CPU的利用率。 程序中断方式&#xff1…

极简云验证 download.php 文件读取漏洞复现

0x01 产品简介 极简云验证是一款开源的网络验证系统&#xff0c;支持多应用卡密生成&#xff1a;卡密生成 单码卡密 次数卡密 会员卡密 积分卡密、卡密管理 卡密长度 卡密封禁 批量生成 批量导出 自定义卡密前缀等&#xff1b;支持多应用多用户管理&#xff1a;应用备注 应用版…

数学建模-最优包衣厚度终点判别法(主成分分析)

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是viperrrrrrr~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff…

armlinux-外部中断

s3c2440的中断框图 如果我们单纯配置一个按键的外部中断&#xff0c;就不存在子中断与优先级的问题。 由于是按键的外部中断&#xff0c;通过引脚的高低电平来触发。所以我们要先配置引脚的功能。 我们使用按键1&#xff0c;终端源为EINT8&#xff0c;对应引脚GPG0 通过用户手…

DBU-Net:用于乳腺超声图像中肿瘤分割的双分支U形网络

DBU-Net&#xff1a;用于乳腺超声图像中肿瘤分割的双分支U形网络 摘要引言材料和方法概述所提出的方法 DBU-Net Dual branch U-Net for tumor segmentation in breast ultrasound images 摘要 乳腺超声医学图像通常具有低成像质量沿着不清楚的目标边界。这些问题使得医生在诊断…