树的一些经典 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.mzph.cn/news/637519.shtml

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

相关文章

C语言:函数指针的使用

在C语言中&#xff0c;函数指针是指向函数的指针变量。它可以存储函数的地址&#xff0c;使得可以通过该指针来调用函数。以下是函数指针的基本概念和用法&#xff1a; 一、基本概念&#xff1a; 声明函数指针&#xff1a; returnType (*pointerName)(parameterTypes); 这里 r…

13.1 一个简单的基类

们在类中添加新特性。 继承是种非常好的概念,其基本实现非常简单。但要对继承进行管理,使之在所有情况下都能正常 工作,则需要做…些调整。本章将介绍继承简单的一面和复杂的一面。 - 13.1 一个简单的基类 从个类派生出另一个类时,原始类称为基类,继承类称为派生类。为说明继…

浅析云服务oss/obs/cos对象存储安全攻防

文章目录 前言云存储服务1.1 初识对象存储1.2 腾讯云COS桶1.3 公开读取风险 对象存储桶风险2.1 Bucket Object遍历2.2 Bucket 名称的爆破2.3 Bucket ACL可读写2.4 任意写与文件覆盖2.5 Bucket 域名的接管 AccessKey凭证泄露3.1 行云管家接管主机3.2 Github泄露AK/SK3.3 客户端程…

【题目】2023年国赛信息安全管理与评估正式赛任务书-模块2

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 任务书 模块二 网络安全事件响应、数字取证调查、应用程序安全 比赛时间及注意事项 本阶段比赛时长为180分钟&#xff0c;时间为13:30-16:30。 【注意事项】 比赛结束&#xff0c;不得关机&#xff1b;选手首先…

Chatgpt+Comfyui绘图源码说明及本地部署文档

其他文档地址&#xff1a; ChatgptComfyui绘图源码运营文档 ChatgptComfyui绘图源码线上部署文档 一、源码说明 1、源码目录说明 app_home&#xff1a;app官网源码chatgpt-java&#xff1a;管理后台服务端源码、用户端的服务端源码chatgpt-pc&#xff1a;电脑网页前端源码cha…

两条链表相同位数相加[中等]

优质博文IT-BLOG-CN 一、题目 给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字0之外&#xff0c;这…

【征服Redis12】redis的主从复制问题

从现在开始&#xff0c;我们来讨论redis集群的问题&#xff0c;在前面我们介绍了RDB和AOF两种同步机制&#xff0c;那你是否考虑过这两个机制有什么用呢&#xff1f;其中的一个重要作用就是为了集群同步设计的。 Redis是一个高性能的键值存储系统&#xff0c;广泛应用于Web应用…

【React】Redux的使用详解

文章目录 Redux的三大原则Redux官方图react-redux使用 1、创建store管理全局状态​ 2、在项目index.js根节点引用 3、 在需要使用redux的页面或者组件中&#xff0c;通过connect高阶组件映射到该组件的props中 redux中异步操作如何使用redux-thunkcombineReducers函数 Re…

数据结构和算法笔记4:排序算法-归并排序

归并排序算法完全遵循分治模式。直观上其操作如下&#xff1a; 分解&#xff1a;分解待排序的n个元素的序列成各具n/2个元素的两个子序列。解决&#xff1a;使用归并排序递归地排序两个子序列。合并&#xff1a;合并两个已排序的子序列以产生已排序的答案。 我们直接来看例子…

Flutter 与 Android原生 相互通信:BasicMessageChannel、MethodChannel、EventChannel

前言 本文主要讲解&#xff0c;使用不同的 Channel 让 Flutter 和 Android原生 进行通信&#xff0c;由于只是讲解两端通信&#xff0c;所以可视化效果不好&#xff1b; 不过我写了一篇专门讲解 Flutter 嵌入 Android原生View的文章 Flutter 页面嵌入 Android原生 View-CSDN…

小程序使用echarts图表-雷达图

本文介绍下小程序中如何使用echarts 如果是通过npm安装&#xff0c;这样是全部安装的&#xff0c;体积有点大 我这边是使用echarts中的一个组件来实现的&#xff0c;下边是具体流程&#xff0c;实际效果是没有外边的红色边框的&#xff0c;加红色边框的效果是这篇说明 1.echa…

IDEA的database使用

一、数据据库 在使用database之前&#xff0c;首先你的电脑要安装好了数据库并且启动。 MySQL卸载手册 链接&#xff1a;https://pan.baidu.com/doc/share/AVXW5SG6T76puBOWnPegmw-602323264797863 提取码&#xff1a;hlgf MySQL安装图解 链接&#xff1a;https://pan.baidu.…

机器学习笔记——机器学习的分类

1 机器学习是啥 机器学习是人工智能的一个分支&#xff0c;它是一门研究机器获取新知识和新技能&#xff0c;并识别现有知识的学问。 机器学习已广泛应用于数据挖掘、计算机视觉、自然语言处理、生物特征识别、搜索引擎、医学诊断、检测信用卡欺诈、证券市场分析、DNA 序列测…

用Python实现Excel中的Vlookup功能

目录 一、引言 二、准备工作 三、实现Vlookup功能 1、导入pandas库 2、准备数据 3、实现Vlookup功能 4、处理结果 5、保存结果 四、完整代码示例 五、注意事项 六、总结 一、引言 在Excel中&#xff0c;Vlookup是一个非常实用的函数&#xff0c;它可以帮助我们在表…

Web概述

Web 概述&#xff1a;Web是World Wide Web的简称&#xff0c;是一个由许多互联网服务组成的信息空间。它由超文本文档、图像、视频和其他多媒体资源组成&#xff0c;并通过超文本传输协议&#xff08;HTTP&#xff09;进行传输。特点&#xff1a;Web的主要特点是其开放性和可访…

java数据结构与算法刷题-----LeetCode485. 最大连续 1 的个数

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 法一&#xff0c;双指针2. 法二&#xff1a;变量计数 1. 法一…

Unity 面试篇|(八)Unity机试篇 【全面总结 | 持续更新】

目录 1.假设当前市场价一只鸡10元&#xff0c;一只鸭12元5角。请写一个函数ShowPrice&#xff0c;输入参数分别为鸡和鸭的个数&#xff08;非负整型&#xff09;&#xff0c;功能为显示出总价钱&#xff0c;精确到分。例如调用ShowPrice&#xff08;5,10&#xff09;后输出175.…

63 C++ 多线程 timed_mutex,recursive_timed_mutex

前提 &#xff1a;以往的mutex如果拿锁子拿不到&#xff0c;就会一直等待。 timed_mutex 和 recursive_timed_mutex则不同&#xff0c;这两个提供了方法&#xff0c;可以不一直等待。 try() 方法--mutex 和 timed_mutex 都有&#xff0c;且说明都一样 bool try_lock();(C11 起)…

vant组件库的简单使用

1. 组件库的选择 组件库并不是唯一的&#xff0c;常用的组件库还有以下几种&#xff1a; pc 端:element-uielement-plus iviewelement-plus iviewant-design移动端&#xff1a;vant-uiMint UI (饿了么)Cube UI (滴滴)… 2. vant组件库 主要参考官网&#xff1a;Vant官网 3…

面对不平衡二元分类问题是否需要使用SMOTE技术?

摘要 在训练分类模型之前平衡数据是解决表格数据中不平衡二元分类任务的流行技术。平衡通常是通过复制少数样本或生成合成少数样本来实现的。虽然众所周知&#xff0c;平衡对每个分类模型的影响不同&#xff0c;但大多数先进的实证研究并未将强大的最先进&#xff08;SOTA&…