Hard | LeetCode 297 | 剑指 Offer 37. 序列化二叉树 | 层次遍历二叉树
Hard | LeetCode 297 | 剑指 Offer 37. 序列化二叉树
请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5
序列化为 "[1,2,3,null,null,4,5]"
方法一:使用数组存储完全二叉树
- 采用完全二叉树的方法进行序列化和反序列化。可以用数组存取。并且左孩子和右孩子可以通过下标获取。如果当前节点为
i
, 那么左孩子下标为2 * i
, 右孩子下标为2 * i + 1
。在序列化时, (1) 先求树高, 确定数组的大小(也可以动态扩容, 参考ArrayList的动态扩容方法)。(2) 然后先序遍历二叉树, 将左右孩子分别放到数组当中。此时如果左右孩子为空, 左右可以存为空值。(3) 根据前面的数组, 将其序列化一个字符串。同时将空值修改为一个表示空值标记的字符串即可。 - 在反序列化时, (1) 将字符串先反序列化为数组, (2) 将数组采用递归的方式反序列化为树。其左右孩子与双亲节点特定的下标关系, 可以很容易找到左右孩子
方法二:层次遍历二叉树
-
序列化二叉树时, 采用层次遍历的方法, 将遍历到的每个节点的值加入到结果当中, 如果某个节点的孩子为NULL, 也要将此加入到结果当中。
-
反序列二叉树时, 依据序列化二叉树时层次遍历的特性, 进行反序列即可。
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "null";
}
StringBuilder res = new StringBuilder();
// 这里必须使用链队, 因为ArrayDeque是不允许存NULL值的。
Deque<TreeNode> queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node != null) {
res.append(node.val).append(",");
queue.add(node.left);
queue.add(node.right);
} else {
res.append("null,");
}
}
return res.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if ("null".equals(data)) {
return null;
}
String[] nodes = data.split(",");
TreeNode root = new TreeNode(Integer.valueOf(nodes[0]));
Deque<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
int i = 1;
while(!queue.isEmpty()) {
// 每次出队的元素都是挡当前数组元素的双亲节点,
TreeNode node = queue.poll();
if (!"null".equals(nodes[i])) {
node.left = new TreeNode(Integer.valueOf(nodes[i]));
queue.add(node.left);
}
i++;
if (!"null".equals(nodes[i])) {
node.right = new TreeNode(Integer.valueOf(nodes[i]));
queue.add(node.right);
}
i++;
}
return root;
}