题目:
请实现两个函数,分别用来序列化和反序列化二叉树。你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
提示:输入输出格式与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
示例:
输入:root = [1,2,3,null,null,4,5] 输出:[1,2,3,null,null,4,5]
解题思路:
首先明确什么叫二叉树的序列化和反序列化:
- 所谓序列化也叫持久化,显然序列化需要将每个结点按照一定的顺序转换为字符串,关键是这个顺序是什么顺序,这个顺序其实就是遍历树的顺序,按照遍历结点的顺序将结点转化为字符串即可,因此先序遍历、中序遍历、后序遍历、按层遍历都可以进行序列化。在序列化时对于任何null或者非null的结点都需要遍历和处理。
- 所谓反序列化是根据一个字符串重新建立一棵二叉树,反序列化是序列化的逆过程,对于一个字符串,首先按照分隔符将其分割为字符串数组,每个字符串元素代表一个结点,然后开始重建二叉树。由于每个结点再字符串中只保留了一个val值,因此需要根据结点的值val重新构建TreeNode结点对象,并且为这个结点对象的left和right进行赋值。
然后,根据本题的题意选择DFS方法
(1)序列化:
- 递归的第一步都是特例的处理,因为这是递归的终止条件:如果根节点为空,返回‘None’
- 序列化的结果为:根节点值+“,”+左子节点值(进入递归)+“,”+右子节点值(进入递归)
- 递归就是不断将“根节点”值加入结果中的过程
(2)反序列化
先将字符串转换为列表,然后进入递归:
- 弹出左侧元素,即队列出队
- 如果元素为“None”,返回None,否则新建一个值为弹出元素的新节点,其左子节点为队列的下一个元素,进入递归;右子节点为队列的下下个元素,也进入递归
- 递归就是不断将子树的根节点连接到父节点的过程
代码:
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
if not root:
return 'None'
return str(root.val) + ',' + str(self.serialize(root.left)) + ',' + str(self.serialize(root.right))
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
def dfs(dataList):
val = dataList.pop(0)
if val == 'None':
return None
root = TreeNode(int(val))
root.left = dfs(dataList)
root.right = dfs(dataList)
return root
dataList = data.split(',')
return dfs(dataList)
复杂度:
- 时间复杂度:O(N)
- 空间复杂度:O(N)