题目

请实现两个函数,分别用来序列化和反序列化二叉树。

你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

提示:输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

示例:

输入:root = [1,2,3,null,null,4,5]

输出:[1,2,3,null,null,4,5]


思路

通常使用的前序、中序、后序、层序遍历记录的二叉树的信息不完整,即唯一的输出序列可能对应着多种二叉树可能性。题目要求的序列化和反序列化是可逆操作 。因此,序列化的字符串应携带完整的二叉树信息 。

观察题目示例,序列化的字符串实际上是二叉树的 “层序遍历”(BFS)结果,本题也采用层序遍历。

为完整表示二叉树,考虑将叶节点下的 null 也记录。在此基础上,对于列表中任意某节点 node ,其左子节点 node.left 和右子节点 node.right 在序列中的位置都是唯一确定的。

序列化 Serialize :

StringBuilder对象代表一个字符序列可变的字符串,当一个StringBuilder被创建以后,通过StringBuilder提供的append()(拼接方法)、insert()、reverse()、setCharAt()、setLength()等方法可以改变这个字符串对象的字符序列。一旦通过StringBuilder生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

String,StringBuilder,StringBuffer的区别:

StringBuilder sb = new StirngBuilder();
sb.append("a").append("b").append("c").append("d");
String str = "";
str += "a";
str += "b";
str += "c";
str += "d";

1.运行速度由快到慢为:StringBuilder > StringBuffer > String

String最慢的原因:String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的。StringBuilder和StringBuffer,字符串是存放在char[]中的,char[]是存放在堆中的。 相比String每次+都重新创建一个String对象,重新开辟一段内存不同,StringBuilder和StringBuffer的append都是直接把String对象中的char[]的字符直接拷贝到StringBuilder和StringBuffer的char[]上,效率比String的+高得多。当然,当StringBuilder和StringBuffer的char[]长度不够时,也会重新开辟一段内存。

2.在线程安全上,StringBuilder是线程不安全的,而StringBuffer是线程安全的

如果一个StringBuffer对象在字符串缓冲区被多个线程使用时,StringBuffer中很多方法可以带有synchronized关键字,所以可以保证线程是安全的,但StringBuilder的方法则没有该关键字,所以不能保证线程安全,有可能会出现一些错误的操作。

所以如果要进行的操作是多线程的,那么就要使用StringBuffer,但是在单线程的情况下,还是建议使用速度比较快的StringBuilder。

总结:

String:适用于少量的字符串操作的情况;

StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况;

StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况。

借助队列,对二叉树做层序遍历,并将越过叶节点的 null 也打印出来。

  • 特例处理: 若 root 为空,则直接返回空字符串 " " ;
  • 初始化: 序列化字符串build;队列 queue (根节点 root 先入队);
  • 层序遍历: 当 queue 为空时跳出;
  1. 节点出队,记为 t ;
  2. 若 t 不为空:① 将 t 的左、右子节点入队,② 添加字符 t.val;
  3. 否则(若 t 为空):添加 "null" ;
  • 返回值: build.toString();

反序列化 Deserialize :

1.split() 方法根据匹配给定的正则表达式来拆分字符串

注意: " . " 、 " $ "、 " | " 和 " * " 等转义字符,必须得加 " \\ "。

注意:多个分隔符,可以用" | "作为连字符。

语法:

stringObj.split(String regex, int limit);
  • stringObj -- 必选项。要被分解的 String 对象。该对象不会被 split 方法修改。

  • regex -- 可选项。正则表达式分隔符。如果忽略该选项,返回包含整个字符串的单一元素数组。

  • limit -- 可选项。分割的份数。该值用来限制返回数组中的元素个数。

返回值:字符串数组。

2.int num = Integer.parseInt(str)将字符串转换成成整数。

利用队列按层构建二叉树,借助一个指针 i 指向节点 t 的左、右子节点,每构建一个 t 的左、右子节点,指针 i 就向右移动 1 位。

  • 特例处理: 若 data 为空,直接返回 null ;
  • 初始化: 序列化字符串数组 s(用逗号隔开);队列 queue(包含 root );根节点 root (值为 s[0] );指针 i = 1 ;
  • 按层构建: 当 queue 为空时跳出;
  1. 节点出队,记为 t;
  2. 构建 t 的左子节点:t.left 的值为 s[i] ,并将 t.left 入队;执行 i++;
  3. 构建 t 的右子节点:t.right 的值为 s[i] ,并将 t.right 入队;执行 i++;
  • 返回值: 返回根节点 root 即可;

代码

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/public class Codec {// Encodes a tree to a single string.序列化成字符串public String serialize(TreeNode root) {if(root == null) {return "";}StringBuilder build = new StringBuilder();Queue<TreeNode> queue = new LinkedList<>();queue.add(root);while(!queue.isEmpty()) {TreeNode t = queue.poll();if(t != null) {queue.add(t.left);queue.add(t.right);build.append(t.val + ",");} else {build.append("null,");}}return build.toString();}// Decodes your encoded data to tree.反序列化字符串public TreeNode deserialize(String data) {if(data == null || data.length() <= 0) {return null;}String[] s = data.split(",");//切割函数Queue<TreeNode> queue = new LinkedList<>();TreeNode root = new TreeNode(Integer.parseInt(s[0]));//将字符串解析成整数queue.add(root);int i = 1;while(!queue.isEmpty()) {//出队TreeNode t = queue.poll();//构建左子节点if(!s[i].equals("null")) {TreeNode left = new TreeNode(Integer.parseInt(s[i]));t.left = left;queue.add(left);} i++;//构建右子节点if(!s[i].equals("null")) {TreeNode right = new TreeNode(Integer.parseInt(s[i]));t.right = right;queue.add(right);}i++;}return root;}
}// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

35-剑指 Offer 37. 序列化二叉树相关推荐

  1. 【LeetCode】剑指 Offer 37. 序列化二叉树

    [LeetCode]剑指 Offer 37. 序列化二叉树 文章目录 [LeetCode]剑指 Offer 37. 序列化二叉树 package offer;import java.util.Link ...

  2. 剑指 Offer 37. 序列化二叉树

    题目 序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据. 请设计一个算法来实 ...

  3. 【LeetCode笔记】剑指Offer 37. 序列化二叉树(Java、二叉树、序列化、BFS、队列)

    文章目录 题目描述 思路 && 代码 二刷 题目描述 这道题涉及到不少 String.StringBuilder.Integer的转换.处理. 思路 && 代码 序列化 ...

  4. 《剑指offer》-- 序列化二叉树、二叉搜索树的第k个节点、数据流中的中位数、滑动窗口的最大值

    一.序列化二叉树: 1.题目: 请实现两个函数,分别用来序列化和反序列化二叉树. 2.解题思路: (1)根据前序遍历规则完成序列化与反序列化.所谓序列化指的是遍历二叉树为字符串:所谓反序列化指的是依据 ...

  5. 《剑指offer》序列化二叉树

    题目:请实现两个函数,分别用来序列化和反序列化二叉树 解析:首先存储二叉树的先序遍历,遇到null就添加"#," 否则添加"值,".构件二叉树的时候也是用先序遍 ...

  6. [剑指offer] 61. 序列化二叉树

    题目描述 请实现两个函数,分别用来序列化和反序列化二叉树 题目很差,没有测试样例. 默认是先序遍历序列化. class Solution {public:vector<int> vec;v ...

  7. 【LeetCode】剑指 Offer 07. 重建二叉树

    [LeetCode]剑指 Offer 07. 重建二叉树 文章目录 [LeetCode]剑指 Offer 07. 重建二叉树 package offer;import java.util.ArrayD ...

  8. 【LeetCode】剑指 Offer 68 - II. 二叉树的最近公共祖先

    [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 文章目录 [LeetCode]剑指 Offer 68 - II. 二叉树的最近公共祖先 一.DFS 一.DFS 祖先的定义 ...

  9. 【LeetCode】剑指 Offer 55 - I. 二叉树的深度

    [LeetCode]剑指 Offer 55 - I. 二叉树的深度 文章目录 [LeetCode]剑指 Offer 55 - I. 二叉树的深度 一.后序遍历(DFS) 二.层序遍历 一.后序遍历(D ...

最新文章

  1. JVM,JDK,JRE和OpenJDK有什么区别?
  2. 查看Eclipse32位还是64位以及Eclipse的编译版本号,查看JDK是32位还是64位
  3. 二分图的最佳完美匹配(模板)
  4. python 求系数矩阵,关于numpy:python-如何在数据矩阵中使用nans计算相关矩阵
  5. ActionScript 3.0编译器编译错误大全【转】
  6. Ruby数据结构-数组和哈希表
  7. 行业案例 | 悬镜DevSecOps智适应威胁管理解决方案获评信通院“2021云安全守卫者计划优秀案例”
  8. 机器学习实战(1)-文本分类
  9. 红帽linux系统服务器下载,redhat linux 下载地址大全 完全整理
  10. 怎样下载安装Firebug和使用Firebug
  11. virtualxposed使用教程_VirtualXposed
  12. python绘制单线图_教你快速利用CAD绘制管道单线图.pdf
  13. Linux文件补全功能,Linux系统自动补全命令有哪些
  14. 杂谈:微信推出赞赏码功能
  15. mysql怎么打开db文件_DB文件扩展名 - 什么是.db以及如何打开? - ReviverSoft
  16. 软件质量的定义及其六大特性(质量模型)
  17. 排列组合和二项式定理
  18. LinuxC TCP实现简易聊天室
  19. matlab upcoef,Matlab小波工具箱的使用2
  20. SpringBoot-Rabbit MQ-设置手动确认ACK-Channel shutdown异常

热门文章

  1. STL中便捷的bitset
  2. python中float函数作用_解析要在Python中浮动的字符串(float()函数)
  3. VB版2004年度专家榜(揭帖时间为2004年度的得分汇总)
  4. 2022年杭州市施工员(装修装饰)考试练习题及答案
  5. 树莓派能做什么知乎_大家用树莓派做过什么实用些的东西,能否分享一下 ?...
  6. 集成开发工具(IDEA)安装与使用
  7. 看看“鲸鱼APP”模式是如何成功的
  8. 在家怎么赚零花钱,分享几种宅家赚钱好方法
  9. 打印实心三角形(半个菱形)
  10. 同程艺龙云原生 K8s 落地实践