二叉搜索树题目:序列化和反序列化二叉搜索树

文章目录

题目

标题和出处

标题:序列化和反序列化二叉搜索树

出处:449. 序列化和反序列化二叉搜索树

难度

6 级

题目描述

要求

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

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

编码的字符串应尽可能紧凑。

示例

示例 1:

输入: root = [2,1,3] \texttt{root = [2,1,3]} root = [2,1,3]

输出: [2,1,3] \texttt{[2,1,3]} [2,1,3]

示例 2:

输入: root = [] \texttt{root = []} root = []

输出: [] \texttt{[]} []

数据范围

  • 树中结点数目在范围 [0, 10 4 ] \texttt{[0, 10}^\texttt{4}\texttt{]} [0, 104] 内
  • 0 ≤ Node.val ≤ 10 4 \texttt{0} \le \texttt{Node.val} \le \texttt{10}^\texttt{4} 0≤Node.val≤104
  • 题目数据保证输入的树是二叉搜索树

前言

这道题要求实现序列化和反序列化二叉搜索树。由于二叉搜索树是特殊的二叉树,因此可以使用「二叉树的序列化与反序列化」的解法实现序列化和反序列化二叉搜索树,但是该解法没有利用二叉搜索树的性质。

和二叉树相比,二叉搜索树的中序遍历序列已知,因此可以使用更简单的方法序列化。

解法

思路和算法

由于反序列化得到原始二叉搜索树需要的信息包括所有结点值,因此序列化结果必须包含二叉搜索树的所有结点值。由于在已知二叉搜索树的前序遍历序列的情况下可以唯一地确定二叉搜索树,因此可以将二叉搜索树的前序遍历序列作为序列化结果,根据二叉搜索树的前序遍历序列即可反序列化得到原始二叉搜索树。

序列化时,使用「二叉树的前序遍历」的解法对二叉搜索树前序遍历。由于序列化结果是字符串,因此将前序遍历结果存入字符串中,每个结点值之间使用逗号分隔。

反序列化时,首先将序列化结果根据逗号分隔成字符串数组,得到二叉搜索树的前序遍历序列,然后使用「前序遍历构造二叉搜索树」的解法根据前序遍历序列构造二叉搜索树。由于序列化结果转化成的数组是字符串类型,因此在构造二叉搜索树时需要将数组中的每个元素转成整数。

代码

java 复制代码
public class Codec {
    public String serialize(TreeNode root) {
        StringBuffer sb = new StringBuffer();
        Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
        TreeNode node = root;
        while (!stack.isEmpty() || node != null) {
            while (node != null) {
                if (!sb.isEmpty()) {
                    sb.append(',');
                }
                sb.append(node.val);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop().right;
        }
        return sb.toString();
    }

    public TreeNode deserialize(String data) {
        if (data.isEmpty()) {
            return null;
        }
        String[] preorder = data.split(",");
        TreeNode root = new TreeNode(Integer.parseInt(preorder[0]));
        Deque<TreeNode> stack = new ArrayDeque<TreeNode>();
        stack.push(root);
        int length = preorder.length;
        for (int i = 1; i < length; i++) {
            int val = Integer.parseInt(preorder[i]);
            TreeNode node = new TreeNode(val);
            if (stack.peek().val > val) {
                stack.peek().left = node;
            } else {
                TreeNode prev = null;
                while (!stack.isEmpty() && stack.peek().val < val) {
                    prev = stack.pop();
                }
                prev.right = node;
            }
            stack.push(node);
        }
        return root;
    }
}

复杂度分析

  • 时间复杂度:序列化和反序列化的时间复杂度都是 O ( n ) O(n) O(n),其中 n n n 是二叉搜索树的结点数。序列化和反序列化的过程中,每个结点都被访问一次。

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是二叉树的结点数。空间复杂度包括栈空间和将字符串转化成的数组。

相关推荐
划破黑暗的第一缕曙光5 小时前
[数据结构]:4.二叉树_堆
c语言·数据结构·二叉树·
老鼠只爱大米11 小时前
LeetCode经典算法面试题 #543:二叉树的直径(深度优先搜索、迭代后续遍历等多种实现方案详细解析)
算法·leetcode·二叉树·二叉树遍历·深度优先搜索·二叉树直径
少许极端1 天前
算法奇妙屋(二十六)-二叉树的深度搜索问题
算法·二叉树·dfs
2401_841495641 天前
【LeetCode刷题】二叉树的中序遍历
数据结构·python·算法·leetcode··递归·遍历
老鼠只爱大米2 天前
LeetCode经典算法面试题 #104:二叉树的最大深度(深度优先搜索、广度优先搜索等多种实现方案详细解析)
算法·leetcode·二叉树·dfs·bfs·深度优先搜索·广度优先搜索
闻缺陷则喜何志丹5 天前
【树 链 菊花】P10418 [蓝桥杯 2023 国 A] 相连的边|普及+
c++·算法·蓝桥杯···菊花
西瓜泡泡奶8 天前
代码随想录算法Day13|(二叉树part3)110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和、222.完全二叉树的节点个数
数据结构·算法·二叉树·平衡二叉树·完全二叉树·二叉树路径·左叶子之和
好评12410 天前
【C++】二叉搜索树(BST):从原理到实现
数据结构·c++·二叉树·二叉搜索树
程序员-King.10 天前
day150—数组—二叉树的锯齿形层序遍历(LeetCode-103)
算法·leetcode·二叉树
程序员-King.11 天前
day151—双端队列—找树左下角的值(LeetCode-513)
算法·leetcode·二叉树·双端队列·队列