二叉树进阶练习

目录

一、根据二叉树创建字符串

二、二叉树的最近公共祖先

三、二叉搜索树与双向链表

四、从前序与中序遍历序列构造二叉树

五、从中序与后序遍历序列构造二叉树

六、二叉树的前序遍历(非递归实现)

七、二叉树的中序遍历(非递归实现)

八、二叉树的后序遍历(非递归实现)


 


一、根据二叉树创建字符串

总结

  1. 左、右子树都为空 --> 不递归遍历左、右子树

  2. 左子树为空,右子树不为空 --> 递归遍历左、右子树

  3. 左子树不为空,右子树为空 --> 只递归遍历左子树

  4. 左、右子树都不为空 --> 递归遍历左、右子树

即当左子树不为空或者右子树不为空时,递归遍历左子树;仅当右子树不为空时,才递归遍历右子树

class Solution {
public:string tree2str(TreeNode* root) {if (root == nullptr)return "";
​string str = to_string(root->val);// 当左子树不为空或者右子树不为空时,递归遍历左子树if (root->left || root->right){str += "(";str += tree2str(root->left);str += ")";}// 仅当右子树不为空时,才递归遍历右子树if (root->right){str += "(";str += tree2str(root->right);str += ")";}return str;}
};


二、二叉树的最近公共祖先

方法一

因为一个节点也可以是它自己的祖先,所以首先判断当前根节点 root 是否等于节点 p 或 q,即判断 p 或 q 是否就是它们的最近公共祖先。

如果不是,则判断 p 和 q 是否分别在 root 的左、右子树中。对于一棵二叉搜索树,可以通过节点的值确定 p 和 q 是在 root 的左子树中,还是右子树中;但对于一棵普通二叉树,只能通过查找的方式确定。

  1. 如果 p 和 q 都在 root 的左子树中,则 p 和 q 的最近公共祖先应该在 root 的左子树中;

  2. 如果 p 和 q 都在 root 的右子树中,则 p 和 q 的最近公共祖先应该在 root 的右子树中;

  3. 如果 p 和 q 分别在 root 的左、右子树中,则 root 就是 p 和 q 的公共祖先。

class Solution {
public:bool search(TreeNode* root, TreeNode* x) {if (root == nullptr)return false;return root == x || search(root->left, x) || search(root->right, x); }
​TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {if (root == p || root == q)  // 一个节点也可以是它自己的祖先return root;
​bool pInLeft, pInRight, qInLeft, qInRight;pInLeft = search(root->left, p);pInRight = !pInLeft;qInLeft = search(root->left, q);qInRight = !qInLeft;
​if (pInLeft && qInLeft)return lowestCommonAncestor(root->left, p, q);else if (pInRight && qInRight)return lowestCommonAncestor(root->right, p, q);elsereturn root;}
};

方法二

如果二叉树的存储结构为三叉链表,即节点结构中增加了一个指向其双亲结点的指针域,那么该问题就可以转化成 相交链表。

如果二叉树的存储结构为二叉链表,我们也可以沿着上述的思路解决该问题,例如:

class Solution {
public:// 找到 root 到 x 的路径bool FindPath(TreeNode* root, TreeNode* x, stack<TreeNode*>& path) {if (root == nullptr)return false;
​path.push(root);if (root == x)return true;if (FindPath(root->left, x, path))return true;if (FindPath(root->right, x, path))return true;path.pop();return false;}
​TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {stack<TreeNode*> pPath, qPath;FindPath(root, p, pPath);FindPath(root, q, qPath);
​while (pPath.size() > qPath.size()){pPath.pop();}while (qPath.size() > pPath.size()){qPath.pop();}
​while (pPath.top() != qPath.top()){pPath.pop();qPath.pop();}return pPath.top();}
};


三、二叉搜索树与双向链表

class Solution {
public:void InOrder(TreeNode* cur, TreeNode*& prev) {if (cur == nullptr)return;
​InOrder(cur->left, prev);
​cur->left = prev;if (prev)prev->right = cur;prev = cur;
​InOrder(cur->right, prev);}
​TreeNode* Convert(TreeNode* pRootOfTree) {if (pRootOfTree == nullptr)return nullptr;
​TreeNode* prev = nullptr;InOrder(pRootOfTree, prev);
​TreeNode* phead = pRootOfTree;while (phead->left){phead = phead->left;}return phead;}
};


四、从前序与中序遍历序列构造二叉树

  1. 在先序序列中,第一个节点一定是二叉树的根节点。

  2. 根据根节点可以将中序序列分割成两个子序列,前一个子序列是根节点的左子树的中序序列,后一个子序列是根节点的右子树的中序序列。

  3. 根据这两个子序列,可以在先序序列中找到对应的左子序列和右子序列。在先序序列中,左子序列的第一个节点是左子树的根节点,右子序列的第一个根节点是右子树的根节点,这样就确定了二叉树的三个节点。同时,左子树和右子树的根节点又可以把左子序列和右子序列划分成两个子序列,如此递归下去,当取尽先序序列中的根节点时,便可得到一棵二叉树。

class Solution {
public:TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder,int L1, int R1, int L2, int R2){// 先序序列的第一个节点一定是根节点TreeNode* root = new TreeNode(preorder[L1]);// 找到根节点在中序序列中的位置int pos = L2;while (pos <= R2){if (preorder[L1] == inorder[pos])break;++pos;}// 判断左子树是否存在if (pos > L2){// 递归构造左子树root->left = _buildTree(preorder, inorder,L1 + 1, L1 + pos - L2, L2, pos - 1);}// 判断右子树是否存在if (pos < R2){// 递归构造右子树root->right = _buildTree(preorder, inorder,R1 - (R2 - pos) + 1, R1, pos + 1, R2);}return root;}
​TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {return _buildTree(preorder, inorder,0, preorder.size() - 1, 0, inorder.size() - 1);}
};


五、从中序与后序遍历序列构造二叉树

class Solution {
public:TreeNode* _buildTree(vector<int>& postorder, vector<int>& inorder,int L1, int R1, int L2, int R2){// 后序序列的最后一个节点一定是根节点TreeNode* root = new TreeNode(postorder[R1]);// 找到根节点在中序序列中的位置int pos = L2;while (pos <= R2){if (postorder[R1] == inorder[pos])break;++pos;}// 判断左子树是否存在if (pos > L2){// 递归构造左子树root->left = _buildTree(postorder, inorder,L1, L1 + pos - L2 - 1, L2, pos - 1);}// 判断右子树是否存在if (pos < R2){// 递归构造右子树root->right = _buildTree(postorder, inorder,R1 - (R2 - pos), R1 - 1, pos + 1, R2);}return root;}
​TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {return _buildTree(postorder, inorder,0, postorder.size() - 1, 0, inorder.size() - 1);}
};


六、二叉树的前序遍历(非递归实现)

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {stack<TreeNode*> st;TreeNode* cur = root;vector<int> v;while (cur || !st.empty()){while (cur){v.push_back(cur->val);st.push(cur);cur = cur->left;}
​TreeNode* top = st.top();st.pop();cur = top->right;}return v;}
};


七、二叉树的中序遍历(非递归实现)

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {stack<TreeNode*> st;TreeNode* cur = root;vector<int> v;while (cur || !st.empty()){while (cur){st.push(cur);cur = cur->left;}
​TreeNode* top = st.top();st.pop();v.push_back(top->val);cur = top->right;}return v;}
};


八、二叉树的后序遍历(非递归实现)

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*> st;TreeNode* prev = nullptr;TreeNode* cur = root;vector<int> v;while (cur || !st.empty()){while (cur){st.push(cur);cur = cur->left; }
​TreeNode* top = st.top();// top 的右子树为空,或者// 上一次访问完的节点是 top 的右子树的根节点,// 说明 top 的右子树已经遍历过了if (top->right == nullptr || top->right == prev){st.pop();v.push_back(top->val);prev = top;}else{cur = top->right;}}return v;}
};

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

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

相关文章

紫光展锐5G芯T820 解锁全新应用场景,让机器人更智能

数字经济的持续发展正推动机器人产业成为风口赛道。工信部数据显示&#xff0c;2023年上半年&#xff0c;我国工业机器人产量达22.2万套&#xff0c;同比增长5.4%&#xff1b;服务机器人产量为353万套&#xff0c;同比增长9.6%。 作为国内商用服务机器人领先企业&#xff0c;云…

应用在儿童平板防蓝光中的LED防蓝光灯珠

现在电子产品多&#xff0c;手机、平板电脑、电子书等等&#xff0c;由于蓝光有害眼睛健康&#xff0c;于是市场上有很多防蓝光的眼镜、防蓝光的手机膜、防蓝光的平板&#xff0c;这些材料和设备到底有没有用&#xff1f;如何正确预防蓝光危害呢&#xff1f; 我们现在所用的灯…

NCTF-2019-Crypto部分 复现

文章目录 SorechildRSAeasyRSAbabyRSA Sore 题目描述&#xff1a; task.py from string import ascii_letters from flag import flagctoi lambda x: ascii_letters.index(x) # 获得所有字母的字符串 itoc lambda x: ascii_letters[x] # 将索引值转换为字母key flag.strip…

关于 Resolution(分辨率、解析力)各单位的意义及相互之间的换算

1、问题背景 最近在调试的项目&#xff0c;有关于对解析力的要求&#xff0c;用 imatest 软件测试 MTF50 的值&#xff0c;如下图所示&#xff0c;可以看到他有不同的单位表示&#xff0c;LW/PH、Cycles/pixel 。另外关于解析力的单位还有LP/mm、L/mm、Cycles/mm、LP/PH&#…

MySQL安装validate_password_policy插件

功能介绍 validate_password_policy 是插件用于验证密码强度的策略。该参数可以设定三种级别&#xff1a;0代表低&#xff0c;1代表中&#xff0c;2代表高。 validate_password_policy 主要影响密码的强度检查级别&#xff1a; 0/LOW&#xff1a;只检查密码长度。 1/MEDIUM&am…

jsoup框架技术文档--java爬虫--基本概念

阿丹&#xff1a; 之前使用python写的爬虫&#xff0c;但是现在项目的技术选型是需要使用jsoup来爬取网页的数据。那就需要重新学习一个框架。首先了解一下整体框架的基本概念。 jsoup的概念 JSoup是一个开源的Java库&#xff0c;它用于处理HTML文档&#xff0c;类似于一个用于…

QT tcpserver

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);// 服务端有QTcpServer库&#xff0c;封装了监听操作server new QTcpServer();// 直接监听&#xff0c;内部根…

Object的常用方法

目录 1.getClass()&#xff1a;获得运行时类型 2.hashCode()&#xff1a;获取哈希值 3.equals()&#xff1a;比较方法 4.clone()&#xff1a;实现对象的浅拷贝方法 5.toString()&#xff1a;输出为String 6.notify()&#xff1a;唤醒线程 7.notifyAll()&#xff1a;…

MVSNet CVPR-2018 学习总结笔记 译文 深度学习三维重建

文章目录 2 MVSNet CVPR-20182.0 主要特点2.1 过程2.2 MVSNet主要贡献2.3 论文简介2.3.1 深度特征提取2.3.2 构造匹配代价2.3.3 代价累计2.3.4 深度估计2.3.5 深度图优化2.4 MVSNet(pytorch版本)2 MVSNet CVPR-2018 MVSNet (pytorch版) 代码注释版 下载 (注释非常详细,代码…

IO流(IO Stream)

​ 一、概述 我们已经系统学习了File 类&#xff0c;并且已经知道 File 类的实例用于表示文件或目录的路径 名。 虽然我们可以通过 File 实例来访问文件或目录的元数据&#xff0c;甚至可以创建、删除文件或目 录&#xff0c;但是&#xff0c;我们却不能通过File实例来访问文…

春秋云镜 CVE-2015-1427

春秋云镜 CVE-2015-1427 ElasticSearch RCE 靶标介绍 ElasticSearch RCE 启动场景 漏洞利用 因查询时至少要求es中有一条数据&#xff0c;所以发送如下数据包&#xff0c;增加一个数据&#xff1a; POST /website/blog/ HTTP/1.1 Host: eci-2zedttamjkr80i9iubel.cloudeci…

Java基础11——抽象类和接口

Java基础11——抽象类和接口 抽象类和抽象方法 区分普通方法和抽象方法 在Java 中&#xff0c;当一个类被 abstract 关键字修饰的时候这个类称为抽象类。当一个类的方法被 abstract 关键字修饰的时候&#xff0c;该方法称为抽象 方法。抽象方法必须定义在抽象类中。当一个方…

leetcode 1921. 消灭怪物的最大数量(每日一题)

最近学习的状态找回很多。慢慢来吧&#xff0c;加油&#xff01; 1921. 消灭怪物的最大数量 你正在玩一款电子游戏&#xff0c;在游戏中你需要保护城市免受怪物侵袭。给你一个 下标从 0 开始 且长度为 n 的整数数组 dist &#xff0c;其中 dist[i] 是第 i 个怪物与城市的 初始…

Linux安装MySQL8.0

又又又又..Linux装MySQL。 删除原有的MySQL 查看安装的mysql信息&#xff1a;rpm -qa|grep -i mysql 删除mysql相关服务&#xff1a;rpm -e --nodeps 查询mysql遗留文件和依赖信息&#xff1a;find / -name mysql 手动删除mysql配置文件&#xff1a;rm -rf /etc/my.cnf 相关…

MySQL锁

MySQL锁 事务事务的隔离级别脏读&#xff0c;不可重复读&#xff0c;幻读 表锁与行锁表锁测试准备测试 行锁测试 读锁与写锁读锁&#xff08;共享锁&#xff09;测试 写锁&#xff08;排他锁&#xff09;测试 元数据锁表级元数据锁表级MDL**&#xff08;Metadata Lock&#xff…

十大排序算法及Java中的排序算法

文章目录 一、简介二、时间复杂度三、非线性时间比较类排序冒泡排序&#xff08;Bubble Sort&#xff09;排序过程代码实现步骤拆解演示复杂度 选择排序&#xff08;Selection Sort&#xff09;排序过程代码实现步骤拆解演示复杂度 插入排序&#xff08;Insertion Sort&#xf…

Ei Scopus检索 | 2024年第三届能源与环境工程国际会议(CFEEE 2024)

会议简介 Brief Introduction 2024年第三届能源与环境工程国际会议(CFEEE 2024) 会议时间&#xff1a;2024年9月1日-3日 召开地点&#xff1a;新西兰奥克兰 大会官网&#xff1a;https://www.cfeee.org/ 2024年第三届能源与环境工程国际会议(CFEEE 2024) 将于2024年12月12日至1…

Struts.xml 配置文件说明

<?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <!--…

【Linux常用命令】

一、防火墙相关 1、查看防火墙状态 systemctl status flrewalld2、如果防火墙是开启状态的&#xff0c;需要关闭 systemctl stop firewalld3、永久行关闭操作&#xff08;禁止开机自启动&#xff09; 因为防火默认是开启状态的&#xff0c;如果只是手动关闭&#xff0c;先次…

elasticsearch集群部署-实操

elasticsearch&#xff08;集群&#xff09; 案例版本&#xff1a;elasticsearch 8.6.2 操作系统&#xff1a;CentOS 7 注意&#xff1a;全程使用普通用户操作。 0、节点信息 节点描述192.168.127.10master192.168.127.11slave…slave02 1、环境配置 1.1 修改文件 /etc/se…