LeetCode 热题 HOT 100 第六十八天 297. 二叉树的序列化与反序列化 困难题 用python3求解

题目地址
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。

请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。

提示: 输入输出格式与 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]

提示:
树中结点数在范围 [0, 10^4] 内
-1000 <= Node.val <= 1000
在这里插入图片描述
在这里插入图片描述

解法:广度优先搜索遍历BFS(层次遍历)
参考:
指路1
指路2

注意理解题目要求,可以通过序列化函数进行序列化和然后通过反序列化恢复即可,因此答案不唯一,只要你的答案能恢复你的序列化二叉树就行了

                     1                                1
                    / \                             /    \
                   2   3                           2      3
                      / \                         / \    / \
                     4   5                      nul nul 4  nul
                        /                              / \
                       6                            nul nul

序列化:例子给的序列化过程是二叉树的层序遍历(广度优先)过程,那我也用层序遍历吧,实际上,你可以采用任意方式,比如深度优先的方式。我们利用队列依次将每一层的节点压入和弹出,保证了层序,压入过程压入该层节点的所有子节点,弹出过程弹出该层所有节点,因为这里只需要序列化,我们不必知道节点是哪一层的,所以只需要清空队列即可。

反序列化:反序列化的过程同样需要队列,这个过程是我们模拟序列化的过程,然后依次将val值给我们构建的二叉树节点。

留意函数输入和输出数据的类型序列化输出字符串,反序列化输入为字符串,不是直接拿来就用,或者直接返回数组就行,要进行一次字符串和数组的转换。

发现很多人割裂了反序列化和序列化的过程,甚至进行反序列化时没有搞清楚序列化的过程,序列化和反序列化是一一对应的,反序列化的方式取决于序列化的方式,而不应该不看序列化只看反序列化的部分,这个过程类似于编码和解码,对同一内容进行反复的编解码,结果不会发生变化,提交没通过的,建议好好看看序列化过程到底是怎么完成的。

序列化:

  • 用BFS遍历树,与一般遍历的不同点是不管node的左右子节点是否存在,统统加到队列中
  • 在节点出队时,如果节点不存在,在返回值res中加入一个”null“;如果节点存在,则加入节点值的字符串形式

反序列化:

  • 同样使用BFS方法,利用队列新建二叉树
  • 首先要将data转换成列表,然后遍历,只要不为null将节点按顺序加入二叉树中;同时还要将节点入队
  • 队列为空时遍历完毕,返回根节点

代码实现:

class Codec:

    def serialize(self, root):
        """Encodes a tree to a single string.
        
        :type root: TreeNode
        :rtype: str
        """
        if not root: return "[]"
        queue = collections.deque()
        queue.append(root)
        res = []
        while queue:
            node = queue.popleft() # 出队
            if node:
                res.append(str(node.val))
                queue.append(node.left)
                queue.append(node.right)
            else: res.append("null")
        return '[' + ','.join(res) + ']'
        # res:['1','2','3','null','null','4','5','null','null','null','null']
        # ''.join(res):123nullnull45nullnullnullnull
        # '[' + ','.join(res) + ']':[1,2,3,null,null,4,5,null,null,null,null] 


    def deserialize(self, data):
        """Decodes your encoded data to tree.
        
        :type data: str
        :rtype: TreeNode
        """
        if data=='[]':
            return None
        
        # data:[1,2,3,null,null,4,5,null,null,null,null]
        # vals:['1','2','3','null','null','4','5','null','null','null','null'] 
        vals, i = data[1:-1].split(','), 1
        root = TreeNode(int(vals[0]))
        queue = collections.deque()
        queue.append(root)
        while queue:
            node = queue.popleft() # 出队
            if vals[i] != "null":
                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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值