题目
链接:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/
问题描述:
解析
方法1:DFS(递归)
递归可以理解为:转交职责
- 递归一棵树,只关注当前的单个节点就好
- 剩下的工作,交给递归完成
- “serialize 函数,你能不能帮我序列化我的左右子树?我等你的返回结果,再追加到我身上。”
- 为什么选择 前序遍历,因为在反序列化时,根|左|右,更容易定位根节点值
- 遇到 null 节点也要翻译成一个特殊符号,反序列化时才知道这里对应 null 节点
序列化 代码
const serialize = (root) => {
if (root == null) return 'X,' // 遇到null节点
const leftSerialized = serialize(root.left) //左子树的序列化字符串
const rightSerialized = serialize(root.right) //右子树的序列化字符串
return root.val + ',' + leftSerialized + rightSerialized // 根|左|右
}
反序列化——也是递归
序列化时是前序遍历,所以序列化字符串呈现这样的排列:
“根|(根|(根|左|右)|(根|左|右))|(根|(根|左|右)|(根|左|右))”
构建树的函数 buildTree
- buildTree 接收的 “状态” 是 list 数组,由序列化字符串转成
- 按照前序遍历的顺序:先构建根节点,再构建左子树,再构建右子树
- list 数组首项是 当前子树的根节点,弹出,先构建它
buildTree 关注当前节点,然后职责转交
- 将 list 数组的首项弹出,考察它
- 如果它为 ‘X’ ,直接返回 null ,没有子树可构建
- 如果它不为 ‘X’,则为它创建 node 节点,并构建子树
- 递归调用 buildTree 构建左子树
- 递归调用 buildTree 构建右子树
- 以 node 为根节点的子树,构建完毕,向上返回
反序列化 代码
const buildTree = (list) => {
// dfs函数
const nodeVal = list.shift() // 当前考察的节点
if (nodeVal == 'X') return null // 是X,返回null给父调用
const node = new TreeNode(nodeVal) // 创建node节点
node.left = buildTree(list) // 构建node的左子树
node.right = buildTree(list) // 构建node的右子树
return node // 返回以node为根节点的子树给父调用
}
const deserialize = (data) => {
const list = data.split(',') // 转成list数组
return buildTree(list) // 构建树,dfs的入口
}
完整实现:
实现1:耗时比较大
public class Codec {
public String rserialize(TreeNode root, String str) {
if (root == null) {
str += "None,";
} else {
str += str.valueOf(root.val) + ",";
str = rserialize(root.left, str);
str = rserialize(root.right, str);
}
return str;
}
public String serialize(TreeNode root) {