算法leetcode|94. 二叉树的中序遍历(多语言实现)
文章目录
- 94. 二叉树的中序遍历:
- 样例 1:
- 样例 2:
- 样例 3:
- 提示:
- 分析:
- 题解:
- rust:
- go:
- c++:
- python:
- java:
94. 二叉树的中序遍历:
给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
样例 1:

输入:root = [1,null,2,3]输出:[1,3,2]
样例 2:
输入:root = []输出:[]
样例 3:
输入:root = [1]输出:[1]
提示:
- 树中节点数目在范围
[0, 100]内 -100 <= Node.val <= 100
分析:
- 面对这道算法题目,二当家的再次陷入了沉思。
- 二叉树的中序遍历和前序遍历,后续遍历是二叉树常用的遍历方式。
- 使用递归方式比循环非递归方式更加简单,直观,易于理解。
- 通常二叉树的中序遍历一定要使用一个栈结构,因为中序遍历的要求是遍历完左子树才能遍历当前节点,但是遍历到了左子树就无法再回到当前节点了,所以一般都是使用压栈的方式,先将当前节点压栈,遍历完左子树再将当前节点出栈,这样空间复杂度就会是 O(n) (递归也相当于使用了栈结构)。
- 说起来这不是什么大问题,但是算法就是要想办法优化降低时间和空间的复杂度,于是寄出一种可以将空间复杂度降低为 O(1) 的中序遍历方式,Morris 中序遍历。
- 事实上Morris 中序遍历不是没有代价的,由于要做额外的节点连接和恢复,相当于用时间换空间。
题解:
rust:
// Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
// pub val: i32,
// pub left: Option<Rc<RefCell<TreeNode>>>,
// pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
// #[inline]
// pub fn new(val: i32) -> Self {
// TreeNode {
// val,
// left: None,
// right: None
// }
// }
// }
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {pub fn inorder_traversal(mut root: Option<Rc<RefCell<TreeNode>>>) -> Vec<i32> {let mut ans = Vec::new();while root != None {if root.as_ref().unwrap().borrow().left != None {// 寻找当前 root 节点的前驱节点:前驱 predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止let mut predecessor = root.as_ref().unwrap().borrow().left.clone();while predecessor.as_ref().unwrap().borrow().right != None&& predecessor.as_ref().unwrap().borrow().right != root {predecessor = predecessor.unwrap().borrow().right.clone();}if predecessor.as_ref().unwrap().borrow().right == None {// 让前驱 predecessor 节点的右指针指向当前 root 节点,继续遍历左子树,之后会再次回到当前 root 节点predecessor.unwrap().borrow_mut().right = root.clone();// 遍历左子树root = root.unwrap().borrow().left.clone();continue;} else {// 左子树遍历完毕又回到了当前 root 节点,让前驱 predecessor 节点的右指针与当前 root 节点断开,恢复原样predecessor.unwrap().borrow_mut().right = None;}}// 遍历当前 root 节点ans.push(root.as_ref().unwrap().borrow().val);// 遍历当前 root 节点的右子树root = root.unwrap().borrow().right.clone();}return ans;}
}
go:
/*** Definition for a binary tree node.* type TreeNode struct {* Val int* Left *TreeNode* Right *TreeNode* }*/
func inorderTraversal(root *TreeNode) []int {var ans []intfor root != nil {if root.Left != nil {// 寻找当前 root 节点的前驱节点:前驱 predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止predecessor := root.Leftfor predecessor.Right != nil && predecessor.Right != root {// 有右子树且没有设置过指向 root,则继续向右走predecessor = predecessor.Right}if predecessor.Right == nil {// 让前驱 predecessor 节点的右指针指向当前 root 节点,继续遍历左子树,之后会再次回到当前 root 节点predecessor.Right = root// 遍历左子树root = root.Leftcontinue} else {// 左子树遍历完毕又回到了当前 root 节点,让前驱 predecessor 节点的右指针与当前 root 节点断开,恢复原样predecessor.Right = nil}}// 遍历当前 root 节点ans = append(ans, root.Val)// 遍历当前 root 节点的右子树root = root.Right}return ans
}
c++:
/*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> ans;while (root != nullptr) {if (root->left != nullptr) {// 寻找当前 root 节点的前驱节点:前驱 predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止TreeNode *predecessor = root->left;while (predecessor->right != nullptr && predecessor->right != root) {predecessor = predecessor->right;}if (predecessor->right == nullptr) {// 让前驱 predecessor 节点的右指针指向当前 root 节点,继续遍历左子树,之后会再次回到当前 root 节点predecessor->right = root;// 遍历左子树root = root->left;continue;} else {// 左子树遍历完毕又回到了当前 root 节点,让前驱 predecessor 节点的右指针与当前 root 节点断开,恢复原样predecessor->right = nullptr;}}// 遍历当前 root 节点ans.emplace_back(root->val);// 遍历当前 root 节点的右子树root = root->right;}return ans;}
};
python:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:def inorderTraversal(self, root: Optional[TreeNode]) -> List[int]:ans = list()while root is not None:if root.left is not None:# 寻找当前 root 节点的前驱节点:前驱 predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止predecessor = root.leftwhile predecessor.right is not None and predecessor.right != root:# 有右子树且没有设置过指向 root,则继续向右走predecessor = predecessor.rightif predecessor.right is None:# 让前驱 predecessor 节点的右指针指向当前 root 节点,继续遍历左子树,之后会再次回到当前 root 节点predecessor.right = root# 遍历左子树root = root.leftcontinueelse:# 左子树遍历完毕又回到了当前 root 节点,让前驱 predecessor 节点的右指针与当前 root 节点断开,恢复原样predecessor.right = None# 遍历当前 root 节点ans.append(root.val)# 遍历当前 root 节点的右子树root = root.rightreturn ans
java:
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public List<Integer> inorderTraversal(TreeNode root) {List<Integer> ans = new ArrayList<Integer>();while (root != null) {if (root.left != null) {// 寻找当前 root 节点的前驱节点:前驱 predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止TreeNode predecessor = root.left;while (predecessor.right != null && predecessor.right != root) {predecessor = predecessor.right;}if (predecessor.right == null) {// 让前驱 predecessor 节点的右指针指向当前 root 节点,继续遍历左子树,之后会再次回到当前 root 节点predecessor.right = root;// 遍历左子树root = root.left;continue;} else {// 左子树遍历完毕又回到了当前 root 节点,让前驱 predecessor 节点的右指针与当前 root 节点断开,恢复原样predecessor.right = null;}}// 遍历当前 root 节点ans.add(root.val);// 遍历当前 root 节点的右子树root = root.right;}return ans;}
}
非常感谢你阅读本文~
欢迎【点赞】【收藏】【评论】三连走一波~
放弃不难,但坚持一定很酷~
希望我们大家都能每天进步一点点~
本文由 二当家的白帽子:https://le-yi.blog.csdn.net/ 博客原创~
相关文章:
算法leetcode|94. 二叉树的中序遍历(多语言实现)
文章目录 94. 二叉树的中序遍历:样例 1:样例 2:样例 3:提示: 分析:题解:rust:go:c:python:java: 94. 二叉树的中序遍历: …...
3.[BUUCTF HCTF 2018]WarmUp1
1.看题目提示分析题目内容 盲猜一波~ : 是关于PHP代码审计的 2.打开链接,分析题目 给你提示了我们访问source.php来看一下 大boss出现,开始详细手撕~ 3.手撕PHP代码(代码审计) 本人是小白,所以第一步&…...
rocky linux9 安装go 即接下去
首先,更新系统的软件包索引以获取最新的软件包信息: sudo dnf update使用以下命令安装 Go 语言: sudo dnf install golang安装完成后,你可以通过以下命令验证 Go 语言是否安装成功: go version4、用相对路径初始化g…...
NLP中的嵌入层
在自然语言处理(NLP)中,嵌入层(Embedding Layer)是一个特殊的层,通常用于深度学习模型的第一层,它的作用是将离散的文本数据(如单词或短语)转换为连续的向量表示。每个单…...
MongoDB文档操作
3.3 文档操作 3.1 文档介绍 文档的数据结构和 JSON 基本一样。 所有存储在集合中的数据都是 BSON 格式。 BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。 文档是一组键值(key-value)对(即 BSON),一个简单的文档例子如下&…...
解决谷歌浏览器下CSS设置字体小于12px无效办法,关于如何在chrome里实现小于12px的文字。
关于如何在chrome里实现小于12px的文字。 当然文字缩小到12px以下本来就一定程度影响到可用性了,建议无视chrome的这个特性。 谷歌浏览器默认最小字体为12px,小于12px的字体它都以12px显示,有时我们需要字体小点,特别是在制作英文…...
springboot(ssm智慧校园之家长子系统 智慧校园系统Java系统
springboot(ssm0智慧校园之家长子系统 智慧校园系统Java系统 开发语言:Java 框架:ssm/springboot vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7(或8.0)…...
RM3100 stm32驱动(硬件i2c)
目录 RM3100接线HAL库I2C函数HAL_I2C_Mem_ReadHAL_I2C_Mem_WriteHAL_I2C_Master_Transmit / HAL_I2C_Master_Receive例子 HSHAKE寄存器 cubemx配置RM3100寄存器驱动最终效果 RM3100接线 原理图 SA0 SA1接地,此时i2c设备地址为0100000,即0x20 如果SA0接…...
视觉学习(7) —— 接收数据和发送数据以及全局变量和浮点数
1、前提 创建一个四个字节的地址 2、发送数据 (1)直接发送数据 再观察地址里的值 与我们想要值不一样 输入0,而实际值则为 结论:直接输入值到地址,值会发生变化 (2)走全局变量发送数据 添加全…...
leetcode 1576. 替换所有的问号(easy)(优质解法)
链接:1576. 替换所有的问号 代码: class Solution {public String modifyString(String s) {char[] charSs.toCharArray();int lengthcharS.length;//遍历找到 ?for(int i0;i<length;i){if(charS[i]?){//遍历 a ~ z 选择一个合适的字符来…...
Advanced IP Scanner - 网络扫描器
Advanced IP Scanner - 网络扫描器 1. Advanced IP ScannerReferences https://www.advanced-ip-scanner.com/cn/ 可靠且免费的网络扫描器可以分析 LAN。该程序可扫描所有网络设备,使您能够访问共享文件夹和 FTP 服务器,(通过 RDP 和 Radmin) 远程控制…...
搜索百度百科官方创建入口,怎么创建更新公司的百度百科词条呢?
在百度搜索百度百科找到百度百科官方创建入口,可以上传并创建公司类的百度百科词条,创建词条后还可以再修改更新百科词条,最终完善好的百度百科词条将会在百度上获得大量曝光。那么百度百科可以怎么创建,下面洛希爱做百科网把十多…...
大数据与人工智能|全面数字化战略与企业数字化转型(第1节 )
要点一:培养跨学科思维 在分析时,需要采用多学科的思维方式 结果不重要,重要的是如何提炼现象、分析问题和得出结论的过程。 1. 介绍了锤子精神和多学科思维方式的重要性。指出了只从自身学科出发解决问题的局限性。 2. 提倡跨学科思维方式&a…...
【四】【C语言\动态规划】地下城游戏、按摩师、打家劫舍 II,三道题目深度解析
动态规划 动态规划就像是解决问题的一种策略,它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题,并将每个小问题的解保存起来。这样,当我们需要解决原始问题的时候,我们就可以直接利…...
【大数据存储与处理】开卷考试总复习笔记
文章目录 实验部分一、 HBase 的基本操作1. HBase Shell入门2. HBase创建数据库表3. HBase数据操作4. HBase删除数据库表5. HBase Python基本编程 before二、 HBase 过滤器操作1.创建表和插入数据2.行键过滤器3.列族与列过滤器4.值过滤器5.其他过滤器6.python hbase 过滤器编程…...
HTML 实操试题(一)
创建一个包含标题、段落和链接的基本HTML文档: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><ti…...
创龙瑞芯微RK3568设备树1(修改设备树GPIO和串口)
前言 最近一直在搞3568的东西,涉及到底层的设备树修改,驱动编写等等,忙的焦头烂额的,也没时间往下面写东西了。今天差不多底层的东西快弄完了,把最近的感悟给大家分享下,并且加入点设备树的基础知识。给刚刚…...
R语言【dplyr】——filter保留符合筛选条件的行,以数据的行为单位,创建子集
Package dplyr version 1.1.4 Parameters filter(.data, ..., .by NULL, .preverse FALSE) 参数【.data】:一个数据集(data frame),数据集扩展(比如:tibble),或者 lazy data fra…...
几种串口扩展电路
一、IIC串口扩展电路 LCT200 是一款可以通过 I2C 接口通讯,拓展 2 路独立串口的通讯芯片,同时也支持通过 2 路串口读写 I2C 接口的数据。LCT200 的封装为 TSSOP-20。 主要功能:⚫ 通过对 I2C 接口读写实现拓展 2 路独立串口功能 ⚫ 通过读写…...
实战10 角色管理
目录 1、角色后端接口 2、角色列表查询 2.1 效果图 2.2页面原型代码 2.3 角色api代码 role.js 2.4 查询角色列表代码 4、 新增和编辑角色 5、删除角色 6、分配权限 6.1 分配权限思路 6.2 分配权限回显接口 6.3 分配权限回显前端实现 6.4分配权限后端接口 6.4.1 R…...
DeepFace实战:用5行代码快速搭建一个本地人脸搜索系统(附完整代码)
DeepFace实战:5行代码构建本地人脸搜索系统的工程化实践 人脸识别技术早已不再是实验室里的黑科技,而是能够快速落地的实用工具。今天我们将用Python生态中最轻量级的DeepFace库,从工程化角度构建一个真正可用的人脸搜索系统。不同于简单的AP…...
嵌入式核心板选型指南:从单核到四核的精准配置与实战优化
1. 项目概述:从“固定套餐”到“自助餐”的嵌入式核心板选型变革最近在规划一个工业HMI项目,主控选型时又翻开了飞凌嵌入式的产品手册。看到AM62x系列核心板配置新增了单核、双核、四核的选项,第一反应是:这路子对了。在嵌入式开发…...
STM32 FSMC外部存储器接口配置与调试实战指南
1. 项目概述:为什么FSMC是STM32连接外部存储器的“瑞士军刀”如果你玩过STM32,尤其是那些带屏幕、需要大容量数据缓存或者要跑复杂UI的型号,比如F1、F4、H7系列,那你大概率绕不开一个外设:FSMC,全称Flexibl…...
甲级钢制隔热平开防火窗:技术参数、结构工艺与工程应用解析
一、产品概述甲级钢制隔热平开防火窗严格依照国家消防标准制造,采用加厚冷轧镀锌钢板打造框架,搭配防火填充材料、隔热防火玻璃与专用密封配件,防火隔热、密闭性强,耐用抗腐蚀。相较于低等级防火窗,本品耐火隔热性能更…...
【会议征稿通知 | E3S出版 | EI 、Scopus稳定检索】第十二届能源材料与环境工程国际学术会议(ICEMEE 2026)
第十二届能源材料与环境工程国际学术会议(ICEMEE 2026) 2026 12th International Conference on Energy Materials and Environment Engineering 2026年6月12-14日 | 线上会议 大会官网:www.icemee.net 截稿时间:见官网&#x…...
10个常用密码破解与恢复工具盘点:如何高效找回遗忘的文件密码?
密码破解与恢复工具是普通用户找回遗忘文档密码、安全审计人员进行渗透测试以及 IT 工程师评估应用安全性的常用利器。这些工具通常基于穷举法(Brute Force),并配合密码字典或彩虹表进行攻击。随着计算能力的提升,密码恢复的效率也…...
影刀RPA跨境店群运营架构:Python协同Chromium底层调度与高并发容器化架构
定了。在这场旷日持久的跨境电商反爬风控拉锯战中,我们终于用一套基于 Python 深度协同的分布式微服务调度架构,重塑了跨境千店矩阵的自动化底座。 这几天,科技圈被“DeepSeek V4 首发华为昇腾芯片,国产 AI 开始打破英伟达 CUDA …...
从信号处理到AI:卷积的含参积分本质,如何帮你理解PyTorch中的Conv1d层?
从信号处理到AI:卷积的含参积分本质,如何帮你理解PyTorch中的Conv1d层? 在信号处理领域,卷积操作早已是工程师们耳熟能详的工具。但当我们踏入深度学习的殿堂,面对PyTorch中的nn.Conv1d层时,是否曾疑惑过&a…...
别再死记硬背公式了!用Python动画直观理解SAR距离徙动(附代码)
用Python动画拆解SAR距离徙动:从数学恐惧到视觉理解 雷达工程师们常开玩笑说,合成孔径雷达(SAR)成像有两个门槛:一个是昂贵的硬件设备,另一个是让人望而生畏的数学公式。当我第一次看到距离徙动(…...
Intel 14代酷睿接口更迭:技术推演与用户决策指南
1. 项目概述:一次关于“接口更迭”的深度技术推演最近,关于下一代酷睿处理器的传闻又开始在圈内流传,一个核心的焦点再次被推上风口浪尖:Intel 14代酷睿(Raptor Lake Refresh)可能又要更换CPU插槽接口了。这…...
