目录:
目的
思路
复杂度
记忆秘诀
python代码
目的:
请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。
思路
什么是序列化(Serialize)?
将一棵二叉树转换为字符串,序列化是将树转换成线性结构的过程。
- 使用前序遍历,递归地访问每个节点。
- 用
#
表示空节点,节点值使用逗号连接成字符串。
补充:
- 前序遍历:最常见的选择,适用于二叉树的序列化和反序列化,因为它能够非常直观地描述树的结构,且容易递归实现。
- 中序遍历:通常不用于树的序列化,因为它不能唯一标识二叉树(除非是二叉搜索树)。
- 后序遍历:也能序列化树,但相较于前序遍历,应用场景不那么广泛。
- 层次遍历:适用于特定场景(如完全二叉树),但是实现较为复杂。
因此,尽管可以使用不同的遍历方法来实现序列化和反序列化,但前序遍历通常是最简单、最常用的方法。
什么是反序列化(Deserialize)?
将序列化后的字符串恢复成原始的二叉树。
- 根据序列化的字符串,分割成节点值列表。
- 使用递归方法,通过索引位置逐步重建树结构。
代码逻辑:
1. 序列化:Serialize
方法:
- 初始化一个空列表
result
:这个列表用于存储树的遍历结果。 - 定义一个递归函数
pre_order
:该函数接收一个节点作为参数,采用前序遍历的方法遍历树:- 如果节点为空 (
None
),则将#
作为标记添加到result
中,表示该位置是空节点。 - 如果节点不为空,首先把节点的值转化为字符串并添加到
result
中,然后递归地调用pre_order
对左右子树进行遍历。
- 如果节点为空 (
- 调用
pre_order(root)
:从根节点开始遍历整个树。 - 返回结果:用逗号
,
将result
中的元素连接成一个字符串返回。
2. 反序列化:Deserialize
方法:
- 分割字符串:首先用逗号
,
将序列化字符串分割成一个列表values
,该列表包含了节点值和空节点标记(#
)。 - 初始化一个索引
self.index
:用于跟踪当前处理到的字符串中的位置。 - 定义一个递归函数
build_tree
:该函数根据当前self.index
索引的值构建二叉树:- 如果当前值是
#
,表示当前节点为空,跳过该位置并返回None
。 - 否则,创建一个新的节点,并递归地构建该节点的左子树和右子树。
- 如果当前值是
- 递归地构建树:调用
build_tree()
来构建整棵树。
复杂度
-
时间复杂度:O(n)
- 序列化和反序列化的时间复杂度均为 O(n),其中 n 是节点的数量。每个节点被访问一次。
-
空间复杂度:O(h)
- 其中 h 是树的高度。递归时需要用到递归栈,最坏情况下(完全不平衡的树),空间复杂度为 O(n),在平衡树的情况下为 O(log n)。
记忆秘诀
- 序列化,遍历树:使用前序遍历(根 -> 左 -> 右)来遍历整棵树。
- 空节点用井号标:空节点用
#
来表示。- 节点值,先存储:先把节点的值保存到结果列表。
- 递归左、右子树好:递归处理左子树和右子树。
- 结果串,逗号连:最后用逗号
,
将所有节点值(包括空节点#
)连接成字符串。
反序列化,拆字符串:将序列化字符串用逗号分割成列表。- 遇井号,空节点:遇到
#
,表示空节点,跳过并返回None
。- 值存储,建节点:节点值不为
#
时,创建节点。- 左右子树递归连:递归构建左子树和右子树。
python代码
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:def Serialize(self, root):"""序列化二叉树"""# 使用列表来存储序列化结果result = []def pre_order(node):if node is None:result.append('#') # 使用 # 表示空节点else:result.append(str(node.val)) # 存储节点值pre_order(node.left) # 递归左子树pre_order(node.right) # 递归右子树pre_order(root)return ','.join(result) # 以逗号连接成字符串def Deserialize(self, s):"""反序列化二叉树"""values = s.split(',') # 将字符串分割成节点值列表self.index = 0 # 使用索引来跟踪当前值def build_tree():if self.index >= len(values) or values[self.index] == '#':self.index += 1 # 跳过 # 或者越界return None# 创建节点并递归构建左子树和右子树node = TreeNode(int(values[self.index]))self.index += 1node.left = build_tree() # 递归构建左子树node.right = build_tree() # 递归构建右子树return nodereturn build_tree() # 开始构建树
* 欢迎大家探讨新思路,能够更好的理解和记忆