请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5序列化为 "[1,2,3,null,null,4,5]"
本题的初始代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
可见,序列化二叉树输入为一个根节点,输出为一个字符串;反序列化则是字符串输入,能够重建出二叉树。下面分别进行求解。
1. 序列化部分
输入:树的根节点;
输出:字符串。
思路
其实这非常像第32题:从上到下打印二叉树 Python3广度优先搜索
首先给出32题的代码。用的是辅助队列+BFS
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def levelOrder(self, root: TreeNode) -> List[int]:
if not root:
return []
queue = []
res = []
queue.append(root)
while queue:
# for i in queue:
node = queue[0]
queue = queue[1:]
res.append(node.val)
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
if not queue:
return res
对比32题和本题,可以看到,只要在32题的基础上:
- 将null的节点也保存到res中(目的是为了完整恢复树):
- 整个过程以字符串append的形式完成
就能够得到本题的求解。
总体来说,本题还是使用的层序遍历,具体而言就是BFS+辅助队列的方法。
更改后的代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
# Definition for a binary tree node.
if not root:
return "[]"
queue = []
res = []
queue.append(root)
while queue:
# for i in queue:
node = queue[0]
queue = queue[1:]
if node:
res.append(node.val)
queue.append(node.left)
queue.append(node.right)
else: # node 为 null
res.append("null")
print(str(res))
return str(res)
# return '[' + ','.join(res) + ']'
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
if data == "[]": return
vals, i = data[1:-1].split(','), 1
print(vals)
root = TreeNode(int(vals[0]))
queue = collections.deque()
queue.append(root)
while queue:
node = queue.popleft()
# if vals[i][1] != "'":
if vals[i] != "null":
print(vals[i])
node.left = TreeNode(int(vals[i]))
queue.append(node.left)
i += 1
if vals[i] != "null":
node.right = TreeNode(int(vals[i]))
queue.append(node.right)
i += 1
return root
代码总是改不对...回去洗澡明天再改
之前的代码有问题的原因是在deserialize函数中,无论节点的值是否null,使用vals[i] != "null" 或者 vals[i] != 'null'都会判成True!因此始终会有如下错误:
ValueError: invalid literal for int() with base 10: " 'null'"
node.left = TreeNode(int(vals[i]))
Line 54 in deserialize (Solution.py)
return codec.deserialize(codec.serialize(root))
Line 72 in __helper__ (Solution.py)
ret = __DriverSolution__().__helper__(
Line 85 in _driver (Solution.py)
_driver()
Line 97 in <module> (Solution.py)
原因是因为vals的键值实际上是这样的:
['1', ' 2', ' 3', " 'null'", " 'null'", ' 4', ' 5', " 'null'", " 'null'", " 'null'", " 'null'"]
因此可以把判断语句改成下面的样子:
if vals[i][1] != "'":
这是因为当vals[i]=”‘null’“时,vals[i][1] 才会是" ' ",否则将会是具体的数字。
代码
因此,最终的代码如下:
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
# Definition for a binary tree node.
if not root:
return "[]"
queue = []
res = []
queue.append(root)
while queue:
# for i in queue:
node = queue[0]
queue = queue[1:]
if node:
res.append(node.val)
queue.append(node.left)
queue.append(node.right)
else: # node 为 null
res.append("null")
print(str(res))
return str(res)
# return '[' + ','.join(res) + ']'
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
if data == "[]": return
vals, i = data[1:-1].split(','), 1
print(vals)
root = TreeNode(int(vals[0]))
queue = collections.deque()
queue.append(root)
while queue:
node = queue.popleft()
if vals[i][1] != "'":
# if vals[i] != "null":
print(vals[i])
node.left = TreeNode(int(vals[i]))
queue.append(node.left)
i += 1
if vals[i][1] != "'":
node.right = TreeNode(int(vals[i]))
queue.append(node.right)
i += 1
return root
# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
结果
总结
思路仍旧是之前层序遍历的 BFS+辅助队列 的方法。
但是具体字符串操作时遇到了小问题,可以通过灵活改变判断方式来解决。