递归算法讲解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);}
相关文章:
递归算法讲解2
前情提要 上一篇递归算法讲解在这里 递归算法讲解(结合内存图) 没看过的小伙伴可以进去瞅一眼,谢谢! 递归算法的重要性 递归算法是非常重要的,如果想要进大厂,以递归算法为基础的动态规划是必考的&…...
机器学习第33周周报Airformer
文章目录 week33 AirFormer摘要Abstract一、论文的前置知识1. 多头注意力机制(MSA)2. 具有潜变量的变分模型 二、文献阅读1. 题目2. abstract3. 问题与模型阐述3.1 问题定义3.2 模型概述3.3 跨空间MSA(DS-MSA)3.4 时间相关MSA&…...
设计模式(12):代理模式
一.核心作用 通过代理,控制对对象的访问;可以详细控制访问某个对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。 二.核心角色 抽象角色: 定义代理角色和真实角色的公共对外方法;真实角色: 实现抽…...
前端9种图片格式基础知识, 你应该知道的
彩色深度 彩色深度标准通常有以下几种: 8位色,每个像素所能显示的彩色数为2的8次方,即256种颜色。16位增强色,16位彩色,每个像素所能显示的彩色数为2的16次方,即65536种颜色。24位真彩色,每个…...
ChatGPT 与 OpenAI 的现代生成式 AI(上)
原文:Modern Generative AI with ChatGPT and OpenAI Models 译者:飞龙 协议:CC BY-NC-SA 4.0 序言 本书以介绍生成式 AI 领域开始,重点是使用机器学习算法创建新的独特数据或内容。它涵盖了生成式 AI 模型的基础知识,…...
全量知识系统 程序详细设计之架构设计:一个信息系统架构
统架构,整体设计分成了三部分--三种方面:信息nformation、系统Syste 原文 以下是对全知系统程序详细设计需要的架构规划的考虑。 全知系统架构是一个信息系统架构,整体设计分成了三部分(三种“方面”):信…...
从零开始:成功进入IT行业的方法与技巧
如今,信息技术(IT)行业成为了就业市场上的热门领域。由于其快速发展和广阔的职业机会,许多人希望能够进入这个行业。然而,对于没有任何相关背景知识的人来说,要成功进入IT行业可能会面临一些挑战。本文将分…...
SpringCloud - 如何本地调试不会注册到线上环境(Nacos)?
问题描述 有时候我们需要本地调试注册到 Nacos 上,但是会影响线上服务的 Feign 请求打到本地导致不通影响了线上业务。 原因分析 一般最传统的解决方案就是修改本地 bootstrap.yml 的 spring.cloud.nacos.discovery.namespace spring:application:name: app-serv…...
1.9 面试经典150题 除自身以外数组的乘积
除自身以外数组的乘积 给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法࿰…...
【美团笔试题汇总】2023-09-02-美团春秋招笔试题-三语言题解(CPP/Python/Java)
🍭 大家好这里是KK爱Coding ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新美团近期的春秋招笔试题汇总~ 💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢…...
小黑逆向爬虫探索与成长之路:小黑独立破解毛毛租数据加密与解密
前言 有道和招标网的加密入口定位在前面两期做了详细的介绍,本小结将通过简单的关键词搜索定位到加密与解密入口 数据接口寻找与请求 根据响应数据长度,确定数据接口,发现传入的参数需要加密,响应的结果需要解密,后…...
深入浅出 -- 系统架构之微服务架构常见的六种设计模式
面向服务的架构(SOA) 面向服务的架构(SOA)是一种设计方法,也是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的…...
SSM框架学习——SqlSession以及Spring与MyBatis整合
SqlSession以及Spring与MyBatis整合 准备所需要的JAR包 要实现MyBatis与Spring的整合,很明显需要这两个框架的JAR包,但是只是使用这两个框架中所提供的JAR包是不够的,还需要配合其他包使用: Spring的JAR包MyBatis的JAR包Spring…...
6、【单例模式】确保了一个类在程序运行期间只有一个实例
你好,我是程序员雪球 在软件设计中,单例模式是一种常见的设计模式。它确保了一个类在程序运行期间只有一个实例,并提供了全局访问该实例的方式。单例模式在许多场景中都有广泛的应用,例如共享资源管理、数据库连接、日志记录器等…...
vuex插件实现数据共享
vuex插件 vuex是管理多个vue通用的数据的插件.(状态管理工具,状态是数据) 我们对于多个vue文件之间的共同数据,是用props传递,或者对于一个vue实例对象,进行绑定,传参,也是多次传参,多个文件之间,比较麻烦. 但是我们vuex会创建一个公共对象,从这个公共对象上赋值,比较简单易…...
【吊打面试官系列】Redis篇 - 使用过 Redis 分布式锁么,它是什么回事?
大家好,我是锋哥。今天分享关于 【使用过 Redis 分布式锁么,它是什么回事?】面试题,希望对大家有帮助; 使用过 Redis 分布式锁么,它是什么回事? 先拿 setnx 来争抢锁,抢到之后&#…...
DashOJ-8.奇偶统计
题目链接: 题目详情 - 奇偶统计 - DashOJ 思路: (while循环加if分支语句) 巧用死循环 while(1) 然后在里面第一句就判断输入的数字是否等于0 if(x0) ,如果 等于0就直接break跳出循环 或者用 while(cin>>x) 代…...
车源宝微信小程序源码
源码介绍 车源宝微信小程序源码 images — 存放项目图片文件 pages — 存放项目页面相关文件 store — 存放数据接口文件 utils — 存放时间格式化等文件 演示截图 源码下载 https://download.csdn.net/download/huayula/89082980...
“双碳”目标下资源环境中的可计算一般均衡(CGE)模型应用
我国政府承诺在2030年实现“碳达峰”,2060年实现“碳中和”,这就是“双碳”目标。为了实现这一目标就必须应用各种二氧化碳排放量很高技术的替代技术,不仅需要考虑技术上的可靠性,也需要考虑经济上的可行性。可计算一般均衡模型&a…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
