297.二叉树的序列化与反序列化
难度 困难
题目
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示: 输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅LeetCode序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例1
输入:root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
示例2
输入:root = []
输出:[]
示例3
输入:root = [1]
输出:[1]
示例4
输入:root = [1,2]
输出:[1,2]
解题思路
题目吧啦吧啦一堆,说白了就是将二叉树转换为字符串(序列化),再将这个字符串转换为二叉树(反序列化)。做此题之前,建议大家看看这道题:108.将有序数组转换为二叉搜索树,和这道题有异曲同工之妙,字符串我们也要先转为数组,然后再转为二叉树,至于如何转为二叉树,按先中后序中的哪一种,就要和序列化相对应了。108这题,由于题目所给的数组就是中序遍历的结果,所以我们在转为二叉树的时候,也是根据中序的特点来转化的(中序为左根右,则数组中间值为根,左边为左子树,右边为右子树)。(序列化要和反序列化相对应)
那么对于这道题,我们可以使用前序遍历来解决,使用前序更方便字符串转为二叉树,每次数组的头元素就是根。
序列化:对二叉树进行递归前序遍历,将每个遍历的节点值转为字符串型并拼接,注意每个节点值用逗号隔开,空节点转为字符串就用’None’表示
反序列化:将字符串用逗号作为分隔符转为数组,每次弹出数组的头元素构造成根节点,左子节点和右子节点递归调用数组进行构造,递归终止条件为数组为空时终止,注意要判断遇到字符串为’None’时,就返回None给二叉树节点,构造空节点,意为子节点为空(root=TreeNode(None))。
代码
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
if root is None:
return 'None'
left = self.serialize(root.left)
right= self.serialize(root.right)
return str(root.val) + ',' + str(left) + ',' + str(right)
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
def datotree(data_list):
# 数组为空时,递归终止
if not data_list:
return
first_data = data_list.pop(0) # 取出数组头元素作为根
if first_data == 'None':
return None
root = TreeNode(first_data) # 根
root.left = datotree(data_list) # 左
root.right = datotree(data_list) # 右
return root
if data == 'None':
return None
data_list = data.split(',') # 用逗号作为分隔符,将字符串转为数组
return datotree(data_list)
# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))