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

news2024/11/25 22:40:37

目录

题目:

示例:

分析:

代码:


题目:

示例:

分析:

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

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

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

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

因此我们今天的重点放在这道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.coloradmin.cn/o/973576.html

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

相关文章

外贸开发信这么写,效果更好

很多小伙伴说好像现在无论是精准的发送开发信还是群发邮件&#xff0c;似乎效果都没有以往那么好&#xff0c; 虽然现在的开信已经从简单的纯文字书写改到了图文并茂&#xff0c;也从只介绍自己公司的产品实力晋升到对目标客户的分析探寻&#xff0c; 虽然找到了很多对口的邮…

智慧农旅数字农旅

智慧农旅|数字农旅|智慧文旅|智慧农旅平台|数字农旅平台|产业大脑|农业产业大脑|智慧农业|农业可视化|高标准农田|高标准产业园|数字农业大脑|大棚可视化|大棚物联管控|大棚数字孪生管控|大田物联管控|数字农业|数字乡村|数字乡村可视化|数字农业研学|数字大棚|智慧大棚|农业数…

RHCA之路---EX280(6)

RHCA之路—EX280(6) 1. 题目 Create an application greeter in the project samples which uses the Docker image registry.lab.example.com/openshift/hello-openshift so that it is reachable at the following address only: https://greeter.apps.lab.example.com (Not…

QTday1基础

作业 一、做个QT页面 #include "hqyj.h"HQYJ::HQYJ(QWidget *parent)//构造函数定义: QWidget(parent)//显性调用父类的有参构造 {//主界面设置this->resize(540,410);//设置大小this->setFixedSize(540,410);//设置固定大小this->setWindowIcon(QIcon(&q…

算法 数据结构 双向环形链表 手撸环形链表 环形链表实现容器 环形链表添加修改删除获取大小 环形链表实现自定义容器 手撸容器 双向环形哨兵链表 数据结构(六)

1. 环形链表&#xff1a; 2. 建议先不要看我写得自己先实现下&#xff0c;只将Node内部类复制自己命名得容器内&#xff0c; 实现方法&#xff1a; a. add方法&#xff08;添加到头部&#xff0c;尾部添加&#xff0c;指定位置添加&#xff09; b. get方法&#xff08;获取首部…

中小型ISR无人机海战场的运用与关键技术分析

源自&#xff1a;航空兵器 作者&#xff1a;温亮, 孙晓路, 卫国华, 吕建平, 王波 摘 要 关键词 无人机, 情报侦察监视, 海战场, 发射与回收, 自主控制, 任务载荷 引 言 1 国内外海上中小型无人机发展现状 表1 各国的部分中小型无人机 2 中小型ISR无人机在海战场的运用 2…

ModaHub魔搭社区专访百度智能云李莅:做 AI native 的向量数据库有哪些技术难点?

ModaHub魔搭社区&#xff1a;那这种传统的数据库加向量插件的方式和 AI native 的向量数据库两者之间的区别是什么&#xff1f;做 AI native 的向量数据库有哪些技术难点&#xff1f; 李莅&#xff1a;向量检索算法是向量领域最核心的技术挑战。目前&#xff0c;主流的算法是基…

无涯教程-JavaScript - DAY函数

描述 DAY函数返回日期的日期,由序列号表示。日期以1到31之间的整数形式给出。 语法 DAY (serial number)争论 Argument描述Required/Optionalserial number 您要查找的日期。 应该使用DATE函数或其他公式或函数的输出输入日期。 如,在2008年5月的第23天使用DATE(2008,5,23)…

计算准确率sklearn.accuracy_score

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 计算准确率 sklearn.accuracy_score [太阳]选择题 请问关于以下代码最后输出结果的是&#xff1f; from sklearn.metrics import accuracy_score yp [1, 0, 1, 1] y [1, 0, 0, 1] print(&qu…

2023年9月广州/深圳软考高级信息系统项目管理师认证报名

信息系统项目管理师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职称资…

16-MyCat

一 Mycat概述 1 什么是Mycat 什么是Mycat Mycat是数据库中间件&#xff0c;所谓数据库中间件是连接Java应用程序和数据库中间的软件。 为什么要用Mycat 遇到问题&#xff1a; Java与数据库的紧耦合高访问量高并发对数据库的压力读写请求数据不一致 2 Mycat与其他中间件区别 目…

【校招VIP】产品思维考察之产品设计

考点介绍&#xff1a; 产品经理是那个连接用户需求、团队资源与技术可能性的人,而产品经理思维就是产品思维&#xff0c;做产品首先要具有把握关键点的能力。 产品思维考察之产品设计-相关题目及解析内容可点击文章末尾链接查看&#xff01; 一、考点题目 1. 小红书准备做一…

2023年9月CSPM-3国标项目管理中级认证报名,当然弘博创新

CSPM-3中级项目管理专业人员评价&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…

聚观早报|多邻国推出进阶英文课程;电动汽车成本将高于燃油车

【聚观365】9月5日消息 多邻国即将推出进阶英文课程 未来电动汽车成本仍将高于燃油车 戴尔科技2024财年第二季度营收229亿美元 现代汽车电动汽车销量在8月份环比继续下滑 马斯克称将用X数据训练AI 多邻国即将推出进阶英文课程 语言学习平台多邻国宣布&#xff0c;为了满…

moment.js——实现日期格式的转换——常用api汇总

之前遇到关于日期的转换问题&#xff0c;我常用的解决方法就是通过new Date()进行时间的处理。 其实很多日期的处理&#xff0c;都可以通过moment来直接进行处理&#xff0c;简单方便。 下面的操作都是在引入moment.js或者npm install moment之后的写法。 标准日期格式转化为…

C++信息学奥赛1186:出现次数超过一半的数

#include <bits/stdc.h> using namespace std; int main() {int n;cin >> n; // 输入一个整数nint arr[n]; // 定义一个长度为n的整型数组for (int i 0; i < n; i){cin >> arr[i]; // 输入数组元素}int a, max; // 定义变量a和maxmax a 0; // 初始化ma…

06. 小数和小数精度丢失

1. 将0.1累加100次也得不到10 #include <stdio.h>int main() {float sum 0; // 0.1相加100次for (int i 1; i < 100; i) {sum 0.1; } // 显示结果printf("%f\n", sum); }打印结果&#xff1a; 10.000002以上代码没有错&#xff0c;计算机也没…

【owt-server】AudioSendAdapter分析

owt-server/source/core/rtc_adapter/AudioSendAdapter.cc使用其他线程运行rtprtcpmodule taskrunner分配线程:因此,对rtprtcp的使用都是加了mutex的:首先为音频发送者生成一个随机的ssrc并注册 // SSRCs of this type.std::vector<uint32_t> ssrcs_;发送还要向rtprtc…

【Unity3D赛车游戏优化篇】【九】Unity中如何让汽车丝滑漂移?

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

P3074 [USACO13FEB] Milk Scheduling S(拓扑排序)

思路&#xff1a; 核心&#xff1a;拓扑排序 ans[x]max(ans[x],ans[t]f[x]); 注意比当前大才更新&#xff01;&#xff01;&#xff01; 接下来几乎就是拓扑排序模板啦~ ACcode: #include<bits/stdc.h> using namespace std; #define int long long const int N5e41…