题目描述
请实现两个函数,分别用来序列化和反序列化二叉树
二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。
二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。
例如,我们可以把一个只有根节点为1的二叉树序列化为"1,",然后通过自己的函数来解析回这个二叉树
解题思路
鸽了好久的剑指offer,今天回来看序列化二叉树这道题。前端的话可能会对序列化比较熟悉(不就是JSON字符串嘛),这道题的序列化就是把树变成可以解析的JSON字符串,而反序列化是通过JSON字符串还原树的结构。
一提到树,尤其是二叉树,就想到了递归、迭代,先看递归吧,用DFS的思路,从根节点开始,对左右子树分别进行序列化,最后相加起来。在反序列化的时候,划分出结点并压入队列中,根据前序遍历逐个取出建树。
采用迭代的思路(BFS),也同理。序列化是,用队列存储每一层的结点,按层序遍历优先从左子树的根节点开始扩展,扩展完了再扩展右子树。反序列化则将字符串拆解,然后从队列里取结点,每两个结点作为当前结点的左右结点。
Code
// 递归(DFS)
// 序列化
var serialize = function(root) {
if(!root) return "null,";
return root.val + ',' + serialize(root.left) + serialize(root.right);
};
// 反序列化
const buildTree=(list)=>{
const nodeVal=list.shift();
if(nodeVal=='null') return null;
const node=new TreeNode(nodeVal);
node.left=buildTree(list)
node.right=buildTree(list)
return node
}
var deserialize = function(data) {
const list=data.split(',');
return buildTree(list)
};
// 迭代(BFS)
// 序列化
const serialize = (root) => {
const queue = [root]
let res = []
while (queue.length) {
const node = queue.shift()
if (node) { // 出列的节点 带出子节点入列
res.push(node.val)
queue.push(node.left) // 不管是不是null节点都入列
queue.push(node.right)
} else {
res.push('null')
}
}
return res.join(',')
}
// 反序列化
const deserialize = (data) => {
if (data == 'null') return null
const list = data.split(',')
const root = new TreeNode(list[0])
const queue = [root]
let cursor = 1 // 从list第二项开始遍历
while (cursor < list.length) {
const node = queue.shift() // 父节点出列考察
const leftVal = list[cursor] // 获取左子节点值
const rightVal = list[cursor + 1] // 获取右子节点值
if (leftVal !== 'null') { // 左子节点值是有效值
const leftNode = new TreeNode(leftVal) // 创建节点
node.left = leftNode // 成为当前出列节点的左子节点
queue.push(leftNode) // 作为子树的根节点,入列
}
if (rightVal !== 'null') { // 右子节点值是有效值
const rightNode = new TreeNode(rightVal) // 创建节点
node.right = rightNode // 成为当前出列节点的右子节点
queue.push(rightNode) // 作为子树的根节点,入列
}
cursor += 2 // 指针前进2位
}
return root
}
运行环境:JavaScript (V8 6.0.0)
运行时间:17ms
占用内存:5440k