【力扣每日一题】2023.9.4 序列化和反序列化二叉搜索树

目录

题目:

示例:

分析:

代码:


题目:

示例:

分析:

题目给我们一棵搜索二叉树,要我们将这棵二叉树转变为字符串,同时我们需要根据字符串再变回二叉树,具体的方法我们可以自行制定。

这道题让我想起了力扣的另外一道题:

我们可以把二叉树的前序遍历和中序遍历的结果压缩成字符串。

要由字符串变为二叉树的时候,可以通过字符串分割出前序遍历和中序遍历,再通过前序与中序遍历序列构造二叉树。

因此我们今天的重点放在这道105题上。

我们应该如何通过前序遍历的结果和中序遍历的结果来构造二叉树?

我们先看看两者的结果分别有什么特点。

我们知道,前序遍历和中序遍历对于二叉树的遍历顺序是一样的,都是先遍历左子树再遍历右子树,不一样的是,取节点值的时机不同,前序遍历是在一开始就去了当前节点的值,而中序遍历是在递归遍历完了当前节点的左子树之后才取的值。

因此前序遍历的结果的值的顺序就是我们递归二叉树的顺序,因为前序遍历一递归到节点就取值,因此前序遍历的第一个元素一定是根节点。

而中序遍历,用我的话来说,就是把二叉树压扁,说起来比较抽象。可以参考下面的动图看一看。

因为二叉树压扁之后就是中序遍历的结果,所以结果里某个节点的左边的节点,都在这个节点的左子树上,在这节点右边的节点,都在这个节点的右子树上。

大概懂了两种遍历结果的特点之后,我们来分析如何通过这俩结果来构造一棵二叉树。

我们就以105题的示例一为例。        

中序遍历的结果是:

[ 9 , 3 , 15 , 20 , 7]

前序遍历的结果是:

[ 3 , 9 , 20 , 15 , 7 ]

根据我们刚才说的,前序遍历的结果的第一个元素就是根节点。因此我们构造出的二叉树的根节点的值就是前序遍历的第一个值:3。

而3在中序遍历中,将结果分为了两半,【9】和【15,20,7】。

又根据我们刚才说的,【9】在原本3的左边,所以9在3的左子树,【15,20,7】在3的右边,所以它们仨在3的右子树上。

3的左子树就9一个节点,所以我们可以知道根节点的左子树节点的值就是9,那么问题在于右子树节点的值,有三个备选的值都在右子树上,那么哪一个值是根节点的右子树的根节点的值呢?

这时候我们就需要看前序遍历了,按照顺序来看,开头的3和9我们都用过了,那么接下来轮到的是20,所以根节点的右子树节点的值就是20。

20在中序遍历中,将剩余的结果又分为了两半,是15和7,分别是20的左右子树。至此遍历完毕,我们也就构造完了二叉树。

我们知道如何用前序遍历和中序遍历的结果构造二叉树之后我们再回过头来看看今天的每日一题。

前序遍历和中序遍历相信大家都懂,我们先分别将两个结果集的每个元素之间用一个特殊符号来连接起来,代码中我用的是‘#’,再用另一个特殊符号来连接两个结果集,代码中我用的是‘/’。如此我们就将一棵二叉树序列化了。

反序列化的话,我们只需将前序遍历的结果和中序遍历的结果从序列化后的字符串中提取出来,然后直接使用105题的代码就可以,我在代码中也是这么做的。

我这种做法没有利用到搜索二叉树的特性,并且代码又臭又长,所以仅供大家参考,提供一种思路,可以参考下面的动图来体会一下怎么通过前序和中序遍历来构造二叉树。

代码:

class Codec {
public:vector<int>cache;void qianxv(TreeNode* root){    //前序遍历if(root==nullptr) return;cache.push_back(root->val);qianxv(root->left);qianxv(root->right);}void zhongxv(TreeNode* root){   //中序遍历if(root==nullptr) return;zhongxv(root->left);cache.push_back(root->val);zhongxv(root->right);}// Encodes a tree to a single string.string serialize(TreeNode* root) {  //将前序和中序的结果拼接cache.clear();qianxv(root);string res="";for(auto c:cache) res+="#"+to_string(c);res+='/';   //中间用'/'分隔cache.clear();zhongxv(root);for(auto c:cache) res+="#"+to_string(c);return res;}//力扣105题,前序与中序构造二叉树TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {if(inorder.size()==0) return nullptr;TreeNode* res=new TreeNode(preorder[0]);    //根节点一定是前序遍历的第一个int index=0;for(;index<inorder.size();index++){if(inorder[index]==preorder[0]) break;  //找到根节点在中序遍历的位置}   preorder.erase(preorder.begin());   //移除前序遍历第一个节点vector<int>left,right;//中序遍历的位置的左边是当前节点的左子树if(index!=0) left=vector<int>(inorder.begin(),inorder.begin()+index);//中序遍历的位置的右边是当前节点的右子树  if(index!=inorder.size()-1) right=vector<int>(inorder.begin()+index+1,inorder.end());//传入更新过的前序遍历和中序遍历来构造左右子树res->left=buildTree(preorder,left);res->right=buildTree(preorder,right);return res;}// Decodes your encoded data to tree.TreeNode* deserialize(string data) {vector<int>preorder,inorder;int index=0;while(data[index]!='/'){if(data[index]=='#'){string temp="";index++;while(data[index]!='#'&&data[index]!='/'){temp+=data[index];index++;}preorder.push_back(stoi(temp));}}index++;while(index<data.size()){if(data[index]=='#'){string temp="";index++;while(index<data.size()&&data[index]!='#'){temp+=data[index];index++;}inorder.push_back(stoi(temp));}}return buildTree(preorder,inorder);}
};

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

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

相关文章

明星录制祝福视频:传递温情与关怀的独特方式

在当今社交媒体和数字化时代&#xff0c;明星录制祝福视频已经成为一种新颖而独特的方式&#xff0c;用来表达温馨祝福、分享喜悦&#xff0c;或者为特殊的时刻增添一份特别的意义。无论是生日、结婚、毕业&#xff0c;还是节日、活动等&#xff0c;明星录制的祝福视频能够让人…

Axure RP美容美妆医美行业上门服务交互原型图模板源文件

Axure RP美容美妆医美行业上门服务交互原型图模板源文件&#xff0c;原型内容属于电商APP&#xff0c;区别于一般电商&#xff0c;它的内容是‘美容美发美妆等’上门服务等。大致流程是线上买单&#xff0c;线下实体店核销消费。 附上预览演示&#xff1a;axure9.com/mobile/73…

Android Activity启动流程一:从Intent到Activity创建

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、概览二、应用内启动源码流程 (startActivity)2.1 startActivit…

C#通过ModbusTcp协议读写西门子PLC中的浮点数

一、Modbus TCP通信概述 MODBUS/TCP是简单的、中立厂商的用于管理和控制自动化设备的MODBUS系列通讯协议的派生产品&#xff0c;显而易见&#xff0c;它覆盖了使用TCP/IP协议的“Intranet”和“Internet”环境中MODBUS报文的用途。协议的最通用用途是为诸如PLC&#xff0c;I/…

k8s 启动和删除pod

k8s创建pod pod的启动流程 流程图 运维人员向kube-apiserver发出指令&#xff08;我想干什么&#xff0c;我期望事情是什么状态&#xff09; api响应命令,通过一系列认证授权,把pod数据存储到etcd,创建deployment资源并初始化。(期望状态&#xff09; controller通过list-wa…

MEMS传感器的原理与构造——单片式硅陀螺仪

一、前言 机械转子式陀螺仪在很长的一段时间内都是唯一的选项&#xff0c;也正是因为它的结构和原理&#xff0c;使其不再适用于现代小型、单体、集成式传感器的设计。常规的机械转子式陀螺仪包括平衡环、支撑轴承、电机和转子等部件&#xff0c;这些部件需要精密加工和…

博客程序系统其它功能扩充

一、注册功能 1、约定前后端接口 2、后端代码编写 WebServlet("/register") public class RegisterServlet extends HttpServlet {Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//设置…

哪个视觉语言模型更优?InstructBLIP、MiniGPT-4?全面评估基准LVLM-eHub告诉你

夕小瑶科技说 原创 作者 | 王思若 LLaMA、GPT-3等大型语言模型实现了对自然语言强大的理解和推理能力&#xff0c;为AI社区构筑了强大的语言基座模型。进而&#xff0c;继续迭代的GPT-4&#xff0c;更是赋予了模型处理图像的视觉能力。 如今&#xff0c;构建强大的多模态模型…

PMP是什么?项目管理专业人士资格认证介绍

PMP认证旨在评估和确认具备一定经验和知识的项目管理专业人士的能力。通过获得PMP认证&#xff0c;项目经理可以证明他们具备在各个行业中成功领导和管理项目所需的技能。这些技能包括十二原则、8大绩效等方面的知识。 以下是PMP认证的详细介绍&#xff1a; 1. 资格要求&…

java八股文面试[JVM]——引用计数、可达性分析

要想进行垃圾回收&#xff0c;得先知道什么样的对象是垃圾。 引用计数法 对于某个对象而言&#xff0c;只要应用程序中持有该对象的引用&#xff0c;就说明该对象不是垃圾&#xff0c;如果一个对象没有任何指针对其引用&#xff0c;它就是垃圾。 引用计数法在对象头处维护一…

LINUX内核启动流程-1

1、BIOS启动 硬件设置从OXFFFF0启动:CPU硬件设置加电即进入16位实模式状态运行,CPU硬件逻辑设计为加电瞬间强行将CS的值置为oxF000,IP的值置为0xFFF0,这样CS:IP就指向0xFFFF0这个地址位置。 BIOS程序的入口地址恰恰就是0xFFFF0 ! 也就是说,BIOS程序的第一条指令就设计在…

Linux执行命令

命令格式 主命令 选项 参数&#xff08;操作对象&#xff09;例如&#xff1a; 修改主机名 hostname set-hostname 新名称显示/目录下的文件的详细信息 ls -l /命令 内置命令&#xff08;builtin&#xff09;&#xff1a;shell程序自带的命令。 外部命令&#xff1a;有独立…