树的一些经典 Oj题 讲解

关于树的遍历

先序遍历

我们知道 树的遍历有 前序遍历 中序遍历 后序遍历 然后我们如果用递归的方式去解决,对我们来说应该是轻而易举的吧!那我们今天要讲用迭代(非递归)实现 树的相关遍历
首先呢 我们得知道 迭代解法 本质上也是在模拟递归,因为递归的过程中使用了系统栈,所以我们在迭代的时候也要用Stack来模拟系统栈。
我们要一开始就要创建一个顺序表接收打印的值 最终程序结束输出出来。
首先我们要创建一个栈来存放结点 ,首先我们就要打印根节点的值 ,此时栈中的内容为null,所以我们优先将头结点puth进去栈,然后打印。其实就很好理解 如果树为空 直接就返回了 。

在这里插入图片描述
我们首先从根节点开始遍历 只要节点不为空 就进入循环 就push 进栈 再打印 再去遍历左子树 ,直到左子树为空,就进不来循环 了 我们就要从栈中弹出元素,去遍历他的右子树 但是现在只有一层循环 不能够继续进入回到上面再进入左子树的循环 那怎么办呢 我们就可以再加一层循环在最外面包着他们 判断条件依然是节点不为空 ,但是这样就解决了吗 当然还没有 你去遍历右子树 肯定会最后右孩子结点为空 又怎么返回循环呢 此时已经节点为空了 进不去循环了 但是还没遍历结束, 该怎么办呢 现在栈还没空 也是一个判断条件 我们就可以再外层循环加一个条件栈不为空

最终的实现你们可以参考代码:

public List<Integer> preorderTraversal(TreeNode root) {//先定义一个顺序表去接收List<Integer> list = new ArrayList<>();if(root == null){return list;}//用链表去实现一个栈Deque<TreeNode> stack = new LinkedList<TreeNode>();TreeNode cur = root;while(cur != null || !stack.isEmpty()){while(cur != null){list.add(cur.val);stack.push(cur);cur = cur.left;}cur = stack.pop();cur = cur.right;}return list;}

根据代码去分析上面那棵二叉树 我们就可以输出他的二叉树遍历序列。

中序遍历

通过上面的先序遍历 ,我们可以知道大概的思路 。其实中序遍历迭代(非递归)实现 和先序遍历的实现其实差不太多 就输出的位置换一下 因为是 左 根 右 ,所以我们先去遍历完左子树 ,push进栈。 左子树为空 的时候再从栈中弹出元素 打印元素。
具体代码实现如下:

 public List<Integer> inorderTraversal(TreeNode root) {//先定义一个顺序表去接收List<Integer> list = new ArrayList<>();if(root == null){return list;}//用链表去实现一个栈Deque<TreeNode> stack = new LinkedList<TreeNode>();TreeNode cur = root;while(cur != null || !stack.isEmpty()){while(cur != null){stack.push(cur);cur = cur.left;}cur = stack.pop();list.add(cur.val);cur = cur.right;}return list;}

写到这里 大家是不是觉得 so easy 后序遍历 想直接开敲 ,但是这里提醒大家 后序遍历 没有前序和中序那样简单了 后序会涉及到一个记录结点。 下面我们来分析一下

后序遍历

大体思路和前面两种一样 还是利用栈来实现 因为 后序遍历是 左 右 根
在这里插入图片描述
首先我们先用cur遍历左子树,只要左子树不为空 , 就push进栈 如果左子树为空的话 怎么办呢 ? 我们要从栈中弹出元素吗 那肯定不行啊 因为你还得判断后面有没有右子树 ,所以你只能peek出来看一下。 如果有右子树 我们则让cur = peek出来的节点的右子树,如果右子树为空呢 我们是不是可以pop出栈并且打印出来 。然后现在cur是为空的 进不去循环 然后我们又peek一下栈顶元素 判断他右子树为不为空 但是你会发现现在代码死循环了 他还是会打印刚才的打印过的节点的值 那怎么办呢 ? 很简单 我们定义一个节点prev 来记录一下打印过的结点 。只要peek出来的元素的右孩子 是prev 说明打印过 就直接将他弹出来 打印 所以 现在我们有两个条件可以直接弹出来 打印 然后记录一下, 就是当右孩子为空 或者右孩子是已经打印过的结点 就可以弹出栈顶的元素打印 因为该元素已经是最后一次用了 。
下面我们直接上代码:

 public List<Integer> postorderTraversal(TreeNode root) {List<Integer> list = new ArrayList<>();if(root == null){return list;}//创建一个栈Stack<TreeNode> stack = new Stack<>();TreeNode cur = root;TreeNode prev = null;//用来记录打印过的结点while(cur != null || !stack.isEmpty()){while(cur != null){stack.push(cur);cur = cur.left;}//只能拿出来看一下 不能弹出来TreeNode top = stack.peek();if(top.right == null ||top.right == prev ){ //这里代码会出现死循环  因为会一直在那个结点 所以我们要记录的节点 加一个判断条件stack.pop();list.add(top.val);prev = top;}else{cur = top.right;}}return list;}

二叉树转字符串

题目是这样描述的 给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造成的字符串。

空节点 用一对空括号“()”表示,转化后可以省略所有不影响字符串与原始的二叉树直接的一对一关系的空括号对。

相信大家读完题目会觉得很懵 ,其实题目的情况分为4种 :
1.左右子树都有 则需要 这样加括号:root((left),(right));
2、只有右子树 :root((), (right));
3、只有左子树:root((right));
4、叶子节点 :root;

总的来说 不管有没有左子树 ,只要有右子树 左子树都要加括号。
下面来看几个示例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看完示例 相信大家已经知道思路了 我们直接上代码:

 StringBuilder sb = new StringBuilder();public String tree2str(TreeNode root) {preoderTraveral(root);return sb.toString();}private void preoderTraveral(TreeNode root){if(root == null){return;}sb.append(root.val);if(root.left != null || root.right != null){sb.append("(");preoderTraveral(root.left);sb.append(")");if(root.right != null){sb.append("(");preoderTraveral(root.right);sb.append(")");}}}

看完上面四道题目 相信大家已经想去跃跃欲试了 下面我把题目的链接放在下面

迭代实现前序遍历

迭代实现中序遍历

迭代实现后序遍历

根据二叉树创建字符串

其实关于树的OJ题有很多 感兴趣的可以去力扣或者牛客网上 查找做一下 。

最后感谢大家的浏览 !!!

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

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

相关文章

彩色图像处理之伪彩色图像处理的python实现——数字图像处理

原理 伪彩色图像处理是一种多源信息融合的可视化方法。 处理对象:伪彩色图像处理的对象是多波段遥感图像,例如近红外带、红外带和可见光图像等。 原理:选择不同波段的原始图像作为新的三原色通道(如近红外为红色通道),按RGB模式合成伪彩色图像。 目的:利用不同波段信息融合,实…

力扣645.错误的集合

一点一点地刷&#xff0c;慢慢攻克力扣&#xff01;&#xff01; 王子公主请看题 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数…

视频监控需求记录

记录一下最近要做的需求&#xff0c;我个人任务还是稍微比较复杂的 需求&#xff1a;需要实现一个视频实时监控、视频回放、视频设备管理&#xff0c;以上都是与组织架构有关 大概的界面长这个样子 听着需求好像很简单&#xff0c;但是~我们需要在一个界面上显示两个厂商的视…

在WIN从零开始在QMUE上添加一块自己的开发板(一)

文章目录 一、前言二、源码编译&#xff08;一&#xff09;安装Msys2&#xff08;二&#xff09;配置GCC工具链&#xff08;三&#xff09;安装QEMU构建依赖&#xff08;四&#xff09;下载编译QEMU源码 二、QUME编程基础&#xff08;一&#xff09;QOM机制&#xff08;二&…

Flink处理函数(3)—— 窗口处理函数

窗口处理函数包括&#xff1a;ProcessWindowFunction 和 ProcessAllWindowFunction 基础用法 stream.keyBy( t -> t.f0 ).window( TumblingEventTimeWindows.of(Time.seconds(10)) ).process(new MyProcessWindowFunction()) 这里的MyProcessWindowFunction就是ProcessWi…

什么是中间件?

文章目录 为什么需要中间件&#xff1f;中间件生态漫谈数据库中间件读写分离分库分表引进数据库中间件MyCat 服务端代理模式ShardingJDBC 客户端代理模式 总结 IT 系统从单体应用逐渐向分布式架构演变&#xff0c;高并发、高可用、高性能、分布式等话题变得异常火热&#xff0c…

第十三章 MySQL

第十三章 MySQL 下面是创建数据库操作 删除数据库 右上角选择要操作的数据库 如果关闭了这个控制台&#xff0c;下次如何找到它呢 也可以对其改名

基于YOLOv8的学生课堂行为检测,引入BRA注意力和Shape IoU改进提升检测能力

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;介绍了学生课堂行为检测&#xff0c;并使用YOLOv8进行训练模型&#xff0c;以及引入BRA注意力和最新的Shape IoU提升检测能力 1.SCB介绍 摘要&#xff1a;利用深度学习方法自动检测学生的课堂行为是分析学生课堂表…

IDEA在重启springboot项目时没有自动重新build

IDEA在重启springboot项目时没有自动重新build 问题描述 当项目里面某些依赖或者插件更新了&#xff0c;target的class文件没有找到&#xff0c;导致不是我们需要的效果。 只能手动的清理target文件&#xff0c;麻烦得很 &#xff0c; 单体项目还好说&#xff0c;一次清理就…

如何系统地自学 Python?【附:Python基础入门教程】

如何系统地自学 Python&#xff1f;【附&#xff1a;Python基础入门教程】 一、确定学习目标 在开始学习Python之前&#xff0c;首先需要明确自己的学习目标。是为了入门编程、转行程序员、提升编程能力&#xff0c;还是为了解决特定领域的问题&#xff1f;只有明确了学习目标&…

SpringBoot:详解Bean生命周期和作用域

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 前言一、生命周期二…

react中数据不可变

先看官网 一、不可变数据的概念 不可变数据意味着数据一旦创建&#xff0c;就不能被更改。在React中&#xff0c;每次对数据的修改都会返回一个新的数据副本&#xff0c;而不会改变原始数据。这种方式确保了数据的稳定性和一致性。 二、Props中的不可变数据 在React中&#xf…