LeetCode 练习——449. 序列化和反序列化二叉搜索树

1.题目描述

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

序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。

设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。

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

示例 1:

输入:root = [2,1,3]
输出:[2,1,3]

示例 2:

输入:root = []
输出:[]

2.思路

2.1 代码

序列化和反序列化树,根据题目要求,树必为二查搜索树,根据这一特性,选择使用前序遍历进行序列化(前序、中序、后序遍历都可以,只是反序列化细节不太一样)

  1. 序列化:
    序列化使用前序遍历,在遍历时,使用 StringBuilder 拼接并且使用 “#” 进行分割,遍历完成后删除最后一位 “#” 删除返回,即得到序列化后的用 “#” 分割字符串。
  2. 反序列化:
    反序列化采用分治的思想进行递归。先使用 “#” 对序列化字符串进行拆解,从 left 开始到 right 角标进行处理拆解后的字符串。从 left 开始往后找到第一个比 left 更大的数字的角标 bigger ,由于采用前序遍历进行序列化,因此 left 所对应节点的左子树为 [left+1,bigger-1],右子树为 [bigger,right] 上。再递归这两个区间范围找到左右子树各自的子树即可。

代码如下:

public class Codec {
    public String serialize(TreeNode root) {
        if (root == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder();
        process(builder, root);
        return builder.delete(builder.length() - 1, builder.length()).toString();
    }

    public void process(StringBuilder builder, TreeNode root) {
        if (root == null) {
            return;
        }
        builder.append(root.val).append("#");
        process(builder, root.left);
        process(builder, root.right);
    }

    public TreeNode deserialize(String data) {
        if (data == null) {
            return null;
        }
        String[] split = data.split("#");
        return process2(0, split.length - 1, split);
    }

    public TreeNode process2(int left, int right, String[] split) {
        if (left > right) {
            return null;
        }
        int bigger = left + 1;
        while (bigger <= right && Integer.parseInt(split[bigger]) <= Integer.parseInt(split[left])) {
        bigger++;
        }
        TreeNode node = new TreeNode(Integer.parseInt(split[left]));
        node.left = process2(left + 1, bigger - 1, split);
        node.right = process2(bigger, right, split);
        return node;
    }
}

2.2 测试结果

通过测试


测试结果

3.总结

  • 序列化可以采用前序、中序、后续遍历,这里采用前序遍历序列化
  • 序列化后的字符串需要使用分隔符进行分割
  • 反序列化采用分治思想进行处理
  • left 节点的左子树为 [left+1,bigger-1],右子树为 [bigger,right] ,其中 bigger 为第一个比 left 大的元素角标

你可能感兴趣的:(LeetCode 练习——449. 序列化和反序列化二叉搜索树)