297. 二叉树的序列化与反序列化 - 力扣(LeetCode)
一、题目
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例 1:
输入:root = [1,2,3,null,null,4,5] 输出:[1,2,3,null,null,4,5]
示例 2:
输入:root = [] 输出:[]
示例 3:
输入:root = [1] 输出:[1]
示例 4:
输入:root = [1,2] 输出:[1,2]
提示:
- 树中结点数在范围
[0, 104]
内 -1000 <= Node.val <= 1000
二、代码
/**
* 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) {
// 这里我们用字符串去存储序列化之后的结果,这样就不需要用分隔符分割了,因为容器天然具有分割结构
StringBuilder ans = new StringBuilder();
// 调用先序遍历序列化方法,传入二叉树根节点
pres(root, ans);
// 返回序列化结果
return ans.toString();
}
// 先序遍历序列化
public void pres(TreeNode head, StringBuilder ans) {
// 如果当前节点为空,则将"None,"加入到字符串中,因为空节点也不能忽略
if (head == null) {
// 注意要用逗号分隔
ans.append("None,");
} else {
// 就按照先序遍历的顺序进行遍历,遍历到一个节点,就将该节点转换成字符类型添加到队列中
ans.append(String.valueOf(head.val))
.append(",");
pres(head.left, ans);
pres(head.right, ans);
}
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
// 如果序列化字符串队列为空,则直接返回null
if (data == null || data.length() == 0) {
return null;
}
// 将字符串按逗号都分割出来
String[] dataArray = data.split(",");
Queue<String> dataList = new LinkedList<String>(Arrays.asList(dataArray));
// 调用反序列化方法,并且返回反序列化后构建好的二叉树根节点
return preb(dataList);
}
// 先序遍历反序列化
public TreeNode preb(Queue<String> prelist) {
// 弹出队列头节点
String value = prelist.poll();
// 如果是空节点则返回空,就不再往下创建了,这一条遍历顺序就算是结束了
if ("None".equals(value)) {
return null;
}
// 按照 头 左 右 的顺序去构建二叉树
// 将弹出的节点创建为Node节点
TreeNode head = new TreeNode(Integer.valueOf(value));
head.left = preb(prelist);
head.right = preb(prelist);
// 返回构建好的节点
return head;
}
}
// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));
三、解题思路
序列化
按照先序遍历的顺序,遍历到谁就将谁序列化,并且不能忽略空节点,需要将空节点用占位符补全(占位符就自定义即可)。并且每序列化一个节点,需要用分隔符(分隔符也是自定义即可)将其进行分割(如果转换成字符串的话就需要用分隔符分割,如果是放到有天然分割结构的容器中,就不需要分隔符了)
反序列化
依次消费字符串,先用逗号切分字符串,变为一个数组,数组中每一项是每一个节点的值。然后依次按照数组元素的顺序去消费元素,按照先序遍历的顺序去构建二叉树。