1 题目

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

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

示例:

你可以将以下二叉树:

​ 1

​ / \
2 3
​ / \
​ 4 5

序列化为 “[1,2,3,null,null,4,5]”
提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。

说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/2021-spring-recruitment/5fyjvv/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2 思路

2.1 序列化

序列化就是将二叉树转换成一个字符串表示,可以使用二叉树的层序遍历方式进行存储,等反序列化时在使用同样的方式反序列化回去。与正常的反序列不同的是,这里需要判断当前节点的左右子树是否空才加入队列中,不管当前节点的左右子节点是否为空,那么都将其左右子节点添加到队列中。如下:

1
2
queue.add(t.left); //并需要需要判断是否为空
queue.add(t.right);

2.2 反序列化

反序列化就是将一个字符串表示的树转成一个二叉树的结构,此时同样需要借助一个辅助队列完成,当给定字符串能够表示一棵树时,则进行反序列操作,如果不能,则返回$null$。

反序列化过程中,从左节点到右节点的顺序进行反序列化,当前字符串出的值不为$”null”$,则可以进行反序列化。这里还需要一个索引$index$来标注当前位置上的值是表示左子树还是右子树。

3 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/**
* 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 sb = new StringBuilder();
sb.append("[");
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode t = queue.poll();
if (t != null) {
sb.append(t.val + ",");
queue.add(t.left);
queue.add(t.right);
} else {
sb.append("null,");
}
}
sb.deleteCharAt(sb.length() - 1); // 删除最后一个逗号
sb.append("]");
return sb.toString();
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
TreeNode root = null;
if (data == null || data.equals("[]")) return root;
String[] vals = data.substring(1, data.length() - 1).split(",");
root = new TreeNode(Integer.parseInt(vals[0]));
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int i = 1;
while (!queue.isEmpty()) {
TreeNode t = queue.poll();
//还原左子树
if (!vals[i].equals("null")) {
t.left = new TreeNode(Integer.parseInt(vals[i]));
queue.add(t.left);
}
i++;
//还原右子树
if (!vals[i].equals("null")) {
t.right = new TreeNode(Integer.parseInt(vals[i]));
queue.add(t.right);
}
i++;
}

return root;
}


}

// 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));

写在最后

欢迎大家关注鄙人的公众号【麦田里的守望者zhg】,让我们一起成长,谢谢。
微信公众号