基本思路
无论使用何种「遍历方式」进行二叉树存储,为了方便,我们都需要对空节点有所表示。
其实题目本身的样例就给我们提供了很好的思路:使用层序遍历的方式进行存储,对于某个叶子节点的空节点进行存储,同时确保不递归存储空节点对应的子节点。
层序遍历
我们使用 0x3f3f3f3f 作为无效值(当然也可以不使用数字,使用某个特殊字符进行表示,只要能在反序列时有所区分即可),并建立占位节点 emptyNode 用来代指空节点(emptyNode.val = INF)。
序列化:先特判掉空树的情况,之后就是常规的层序遍历逻辑:
- 起始时,将
root节点入队; - 从队列中取出节点,检查节点是否有左/右节点:
- 如果有的话,将值追加序列化字符中(注意使用分隔符),并将节点入队;
- 如果没有,检查当前节点是否为
emptyNode节点,如果不是emptyNode说明是常规的叶子节点,需要将其对应的空节点进行存储,即将emptyNode入队;
- 循环流程
,直到整个队列为空。
反序列:同理,怎么「序列化」就怎么进行「反序列」即可:
- 起始时,构造出
root并入队; - 每次从队列取出元素时,同时从序列化字符中截取两个值(对应左右节点),检查是否为
INF,若不为INF则构建对应节点; - 循环流程
,直到整个序列化字符串被处理完(注意跳过最后一位分隔符)。
代码:
public class Codec {
int INF = 0x3f3f3f3f;
TreeNode emptyNode = new TreeNode(INF);
public String serialize(TreeNode root) {
if (root == null) return "";
StringBuilder sb = new StringBuilder();
// 使用队列进行层序遍历,起始先将 root 放入队列
Deque<TreeNode> d = new ArrayDeque<>();
d.addLast(root);
while (!d.isEmpty()) {
// 每次从队列中取出元素进行「拼接」,包括「正常节点」和「叶子节点对应的首位空节点」
TreeNode poll = d.pollFirst();
sb.append(poll.val + "_");
// 如果取出的节点不为「占位节点」,则继续往下拓展,同时防止「占位节点」不继续往下拓展
if (!poll.equals(emptyNode)) {
d.addLast(poll.left != null ? poll.left : emptyNode);
d.addLast(poll.right != null ? poll.right : emptyNode);
}
}
return sb.toString();
}
public TreeNode deserialize(String data) {
if (data.equals("")) return null;
// 根据分隔符进行分割
String[] ss = data.split("_");
int n = ss.length;
// 怎么序列化就怎么反序列化
// 使用队列进行层序遍历,起始先将 root 构建出来,并放入队列
TreeNode root = new TreeNode(Integer.parseInt(ss[0]));
Deque<TreeNode> d = new ArrayDeque<>();
d.addLast(root);
for (int i = 1; i < n - 1; i += 2) {
TreeNode poll = d.pollFirst();
// 每次从中取出左右节点对应 val
int a = Integer.parseInt(ss[i]), b = Integer.parseInt(ss[i + 1]);
// 如果左节点对应的值不是 INF,则构建「真实节点」
if (a != INF) {
poll.left = new TreeNode(a);
d.addLast(poll.left);
}
// 如果右节点对应的值不是 INF,则构建「真实节点」
if (b != INF) {
poll.right = new TreeNode(b);
d.addLast(poll.right);
}
}
return root;
}
} - 时间复杂度:
- 空间复杂度:
最后
这是我们「必考真题 の 精选」系列文章的第 No.93 篇,系列开始于 2021/07/01。
该系列会将牛客网中「题霸 - 面试必考真题」中比较经典而又不过时的题目都讲一遍。
在提供追求「证明」&「思路」的同时,提供最为简洁的代码。
欢迎关注,交个朋友 (`・ω・´)


京公网安备 11010502036488号