当前位置: 首页 > news >正文

算法系列--递归

一.如何理解递归

递归对于初学者来说是一个非常抽象的概念,笔者在第一次学习时也是迷迷糊糊的(二叉树遍历),递归的代码看起来非常的简洁,优美,但是如何想出来递归的思路或者为什么能用递归这是初学者很难分析出来的

笔者在学习的过程中通过刷题,也总结出自己的一些经验,总结来说就是要胆大心细,宏观看待问题

其实很多递归的问题如果从宏观的角度去看,其实特别简单,比如二叉树的后序遍历,他无非就是:

  1. 你先给我一个根节点
  2. 访问根节点的左子树
  3. 访问根节点的右子树
  4. 再打印当前节点的值

对于每一个节点的操作都是相同的,如果从宏观的角度看,我们可以把一个复杂的二叉树想象成一个只有三个节点的二叉树
在这里插入图片描述
把二叉树的后序遍历就当做访问这个只有三个节点的二叉树,按照左右根的顺序遍历

dfs(TreeNode root) {if(root == null) return;dfs(root.left);// 访问左节点dfs(root.right);// 访问右结点println(root.val);// 打印当前节点的值
}

大致总结下来递归问题的思路如下:

  1. 分析:根据题目分析,判断是否有重复的子问题,如果有,就可以利用递归解决,设计出函数头,从宏观的角度想,要完成这次操作,这个"接口"需要什么参数(二叉树的遍历需要root,快排需要一个数组和开始结束位置)
  2. 设计函数体:只关注某一个子问题的具体操作,比如二叉树的后序遍历的子问题就完成三步:访问左子树,访问右子树,打印当前节点
  3. 递归出口:确定好递归出口,将子问题分割到最小单元进行确定,比如二叉树的遍历当节点为空时就不需要再去执行任何操作了,直接返回即可,快排,分割到数组只有一个数字或者为空时(l >= r)就不需要继续分治了

二.例题解析:

1.汉诺塔问题

链接:https://leetcode.cn/problems/hanota-lcci/description/

分析:

  1. 函数头:给我三个柱子和盘子数
  2. 函数体:先借助c将a上的n-1个盘子移动到b,然后将a剩余的最大的盘子移动到c,再借助a,将b上的n-1个盘子移动到c
  3. 递归出口:当只有一个盘子的时候,直接移动
    在这里插入图片描述

代码:

class Solution {public void hanota(List<Integer> A, List<Integer> B, List<Integer> C) {int n = A.size();dfs(A,B,C,n);}private void dfs(List<Integer> a, List<Integer> b, List<Integer> c,int n) {// 递归结束条件 只有一个盘子的时候直接移动if(n == 1) {c.add(a.remove(a.size() - 1));return;}// 模拟:借助c,将a上的n-1个盘子移动到b上dfs(a,c,b,n-1);// 将最大的盘子移动到c上c.add(a.remove(a.size() - 1));// 模拟:借助a,将b盘上的n-1个盘子移动到c上dfs(b,a,c,n-1);}
}

2.合并两个有序链表

链接: https://leetcode.cn/problems/merge-two-sorted-lists/

分析:

  1. 函数头:两个链表的头结点
  2. 函数体:判断较小值,合并之后的所有节点,并连接返回的节点
  3. 递归出口:只有一个节点或者为空
    在这里插入图片描述

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode mergeTwoLists(ListNode list1, ListNode list2) {// 递归if(list1 == null) return list2;if(list2 == null) return list1;// 将后面的链表给我合并好,并且返回合并好的节点if(list1.val < list2.val) {list1.next = mergeTwoLists(list1.next,list2);return list1;}else {list2.next = mergeTwoLists(list2.next,list1);return list2;}}
}

3.反转链表

链接: https://leetcode.cn/problems/reverse-linked-list/submissions/514361305/

分析:

  1. 函数头:给我头结点,逆序整个链表
  2. 函数体:逆序之后的所有节点,并且返回逆序之后的头结点,然后和当前节点拼接
  3. 递归出口:只有一个节点或者为空
    在这里插入图片描述

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode reverseList(ListNode head) {// 递归出口if(head == null || head.next == null) return head;// 函数体  你给我逆置后面的所有链表并且返回新的头结点ListNode newhead = reverseList(head.next);// 反转head.next.next = head;head.next = null;return newhead;}
}

4.两两交换链表中的节点

链接: https://leetcode.cn/problems/swap-nodes-in-pairs/

分析:

  1. 函数头:重复子问题就是`给我一个节点,两两交换后面的链表的所有节点
  2. 函数体:关注每一个子问题要干什么,得到交换后的头节点,然后链接这个头结点
  3. 递归出口:空或者只有一个节点
    在这里插入图片描述

代码:

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode swapPairs(ListNode head) {if(head == null || head.next == null) return head;ListNode ret = head.next;// 最终要返回的节点应该是head.next(是头结点的下一个节点)ListNode newHead = swapPairs(head.next.next);head.next.next = head;head.next = newHead;return ret;}
}

5.Pow(x, n)- 快速幂

链接: https://leetcode.cn/problems/powx-n/submissions/514390268/

分析:

  1. 函数头:结合快速幂的思想,递归函数就是求x ^ n的值
  2. 函数体:每一个子问题的操作,得到 x ^ n / 2的值,再判断返回的结果的值
  3. 递归出口:n == 0

在这里插入图片描述
代码:

class Solution {public double myPow(double x, int n) {// 注意n可能为负数return n < 0 ? 1.0 / pow(x,-n) : pow(x,n);}public double pow(double x,int n) {if(n == 0) return 1.0;double tmp = pow(x,n/2);return n % 2 == 0 ? tmp * tmp : tmp * tmp * x;}
}

相关文章:

算法系列--递归

一.如何理解递归 递归对于初学者来说是一个非常抽象的概念,笔者在第一次学习时也是迷迷糊糊的(二叉树遍历),递归的代码看起来非常的简洁,优美,但是如何想出来递归的思路或者为什么能用递归这是初学者很难分析出来的 笔者在学习的过程中通过刷题,也总结出自己的一些经验,总结来…...

【JS】替换文本为emjio表情

最终效果展示 T1 T2 T3 T4 需求 把评论你好帅啊啊啊[开心][开心]&#xff0c;[开心] 替换为图片 思路 正则match提取[开心]到一个数组数组去重创建img标签img标签转文本. 。例&#xff1a;&#xff08;el.outerHTML&#xff09;&#xff0c;将el元素转文本字符串replaceAll…...

Solr完结版

Solr是基于Apache Lucene构建的用于搜索和分析的开源解决方案。提供可拓展索引、搜索功能、高亮显示和文字解析功能。本质是一个java web项目&#xff0c;内嵌Jetty服务器&#xff0c;安装方便。 请求Solr中的控制器&#xff0c;处理完数据后把结果相应给客户端 正向索引&#…...

外包干了5天,技术退步明显。。。。

说一下自己的情况&#xff0c;本科生&#xff0c;19年通过校招进入广州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&a…...

Cronos zkEVM 基于 Covalent Network(CQT)数据可用性 API,推动其 Layer2 DeFi 生态更好地发展

在一项旨在显著改善 DeFi 生态的战略举措中&#xff0c;Cronos 与 Covalent Network&#xff08;CQT&#xff09;携手合作&#xff0c;以期待 Cronos zkEVM 的推出。这一整合&#xff0c;预计将进一步降低以太坊生态系统的交易成本、提升交易速度&#xff0c;并带来更好的交易体…...

基于SpringBoot的高校办公室行政事务管理系统

采用技术 基于SpringBoot的高校办公室行政事务管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 功能清单 教师信息管理 办公室管理 办公物资管…...

Linux系统及操作 (04)

Linux系统及操作 (03) RPM 软件包 网络下载对应软件包光盘镜像文件&#xff0c;具备软件包 Windows 系统软件包的管理 可以指定安装位置安装是集中安装到一个目录Linux 系统 与 Windows 系统相反。 常见的软件包&#xff08;生态&#xff09;类型 电脑入侵99%都是通过软件…...

粒子群算法 - 目标函数最优解计算

粒子群算法概念 粒子群算法 (particle swarm optimization&#xff0c;PSO) 由 Kennedy 和 Eberhart 在 1995 年提出&#xff0c;该算法模拟鸟群觅食的方法进行寻找最优解。基本思想&#xff1a;人们发现&#xff0c;鸟群觅食的方向由两个因素决定。第一个是自己当初飞过离食物…...

关于MySQL数据库的学习3

目录 前言: 1.DQL&#xff08;数据查询语言): 1..1基本查询&#xff1a; 1.2条件查询&#xff1a; 1.3排序查询&#xff1a; 1.3.1使用ORDER BY子句对查询结果进行排序。 1.3.2可以按一个或多个列进行排序&#xff0c;并指定排序方向&#xff08;升序ASC或降序DESC&#…...

笔试题——得物春招实习

开幕式排练 题目描述 导演在组织进行大运会开幕式的排练&#xff0c;其中一个环节是需要参演人员围成一个环形。演出人员站成了一圈&#xff0c;出于美观度的考虑&#xff0c;导演不希望某一个演员身边的其他人比他低太多或者高太多。 现在给出n个参演人员的身高&#xff0c;问…...

动手做简易版俄罗斯方块

导读&#xff1a;让我们了解如何处理形状的旋转、行的消除以及游戏结束条件等控制因素。 目录 准备工作 游戏设计概述 构建游戏窗口 游戏方块设计 游戏板面设计 游戏控制与逻辑 行消除和计分 判断游戏结束 界面美化和增强体验 看看游戏效果 准备工作 在开始编码之前…...

【极简无废话】open3d可视化torch、numpy点云

建议直接看文档&#xff0c;很多都代码老了&#xff0c;注意把代码版本调整到你使用的open3d的版本&#xff1a; https://www.open3d.org/docs/release/tutorial/visualization/visualization.html 请注意open3d应该已经不支持centos了&#xff01; 从其他格式转换成open3d…...

C语言经典算法-6

文章目录 其他经典例题跳转链接31.数字拆解32.得分排行33.选择、插入、气泡排序34.Shell 排序法 - 改良的插入排序35.Shaker 排序法 - 改良的气泡排序 其他经典例题跳转链接 C语言经典算法-1 1.汉若塔 2. 费式数列 3. 巴斯卡三角形 4. 三色棋 5. 老鼠走迷官&#xff08;一&…...

【计算机考研】杭电 vs 浙工大 怎么选?

想求稳上岸的话&#xff0c;其他几所学校也可以考虑&#xff0c;以留在本地工作的角度考虑&#xff0c;这几所学校都能满足你的需求。 如果之后想谋求一份好工作&#xff0c;肯定优先杭电是比较稳的&#xff0c;当然复习的时候也得加把劲。 这个也可以酌情考虑&#xff0c;报…...

激活函数

优秀的激活函数&#xff1a; 非线性&#xff1a;激活函数非线性时&#xff0c;多层神经网络可逼近所有函数 可微性&#xff1a;梯度下降更新参数 单调性&#xff1a;当激活函数是单调的&#xff0c;能保证单层网络的损失函数是凸函数 近似恒等性&#xff1a;当参数初始化为…...

使用Jackson进行 JSON 序列化和反序列化

在Spring应用程序中&#xff0c;您可以通过Maven添加Jackson依赖&#xff0c;并创建一个工具类来封装对象的序列化和反序列化方法。以下是详细步骤&#xff1a; 1. 引入 Jackson 依赖 如果使用 Maven&#xff0c;您可以在 pom.xml 文件中添加以下依赖&#xff1a; <depend…...

Linux/Uinx 系统编程:定时器以及时钟同步

本章讨论了定时器和定时器服务;介绍了硬件定时器的原理和基于Intel x86 的PC中的硬件定时器;讲解了CPU操作和中断处理;描述了Linux中与定时器相关的系统调用、库函数和定时器服务命令;探讨了进程间隔定时器、定时器生成的信号&#xff0c;并通过示例演示了进程间隔定时器。编程…...

(Ubuntu中调用相机花屏)Astra plus深度相机--rgb彩色图像花屏解决方法之一

在调试深度相机的过程中只能能调出深度图像和红外图像 在rviz的image的topic中选择彩色图像的话题不显示图像 1、查看相机的usb序列号 lsusb如上图所示&#xff0c;此相机的USB序列号是2bc5:050f,2bc5:060f 其中050f是显示彩色图像的 在这里可通过拔插相机来确定序列号是哪几…...

iPaaS平台能帮助企业解决什么问题?

随着数字化转型的推进&#xff0c;越来越多的企业开始关注如何提高业务效率和灵活性。iPaaS作为一种新型集成平台&#xff0c;它能够帮助企业解决许多与应用程序和数据集成相关的问题。 它能给企业解决什么问题&#xff1f; 以下是 iPaaS 平台通常能够帮助企业解决的一些问题…...

数学建模(灰色关联度 python代码 案例)

目录 介绍&#xff1a; 模板&#xff1a; 案例&#xff1a;哪些原因影响结婚率 数据标准化&#xff1a; 灰色关联度系数&#xff1a; 完整代码&#xff1a; 结果&#xff1a; 介绍&#xff1a; 灰色关联度是一种多指标综合评价方法&#xff0c;用于分析和评价不同指标之…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

MinIO Docker 部署:仅开放一个端口

MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

离线语音识别方案分析

随着人工智能技术的不断发展&#xff0c;语音识别技术也得到了广泛的应用&#xff0c;从智能家居到车载系统&#xff0c;语音识别正在改变我们与设备的交互方式。尤其是离线语音识别&#xff0c;由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力&#xff0c;广…...

边缘计算网关提升水产养殖尾水处理的远程运维效率

一、项目背景 随着水产养殖行业的快速发展&#xff0c;养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下&#xff0c;而且难以实现精准监控和管理。为了提升尾水处理的效果和效率&#xff0c;同时降低人力成本&#xff0c;某大型水产养殖企业决定…...

Python环境安装与虚拟环境配置详解

本文档旨在为Python开发者提供一站式的环境安装与虚拟环境配置指南&#xff0c;适用于Windows、macOS和Linux系统。无论你是初学者还是有经验的开发者&#xff0c;都能在此找到适合自己的环境搭建方法和常见问题的解决方案。 快速开始 一分钟快速安装与虚拟环境配置 # macOS/…...