【JZ-37】序列化二叉树(树、设计)

题目

在这里插入图片描述参考

算法思路

序列化的结果实际上是二叉树==层序遍历(BFS)==的结果,为了完整表示二叉树,叶节点下的 n u l l null null 也要记录下来。
示例中的二叉树各节点和索引的对应关系为:

n o d e . v a l node.val node.val n o d e node node的索引 n o d e . l e f t node.left node.left的索引 n o d e . r i g h t node.right node.right的索引
1012
2134
3256
null3--
null4--
4578
56910

设当前节点 n o d e node node 索引为 n, m 为列表 [0, n] 中的 null 节点数,则根节点、左子节点、右子节点的列表索引的递推公式为:

n o d e . v a l node.val node.val n o d e node node的索引 n o d e . l e f t node.left node.left的索引 n o d e . r i g h t node.right node.right的索引
等于nulln--
不等于nulln 2 ( n − m ) + 1 2(n-m)+1 2(nm)+1 2 ( n − m ) + 2 2(n-m)+2 2(nm)+2

算法流程

序列化serialize(root):

  1. 特例处理:若 r o o t root root 为空,直接返回空列表
  2. 初始化:包含根节点的队列 q u e u e queue queue,和,序列化结果列表 r e s res res
  3. 层序遍历,当 q u e u e queue queue 为空时跳出:
    1.当前节点出队,记为 n o d e node node
    2.若 n o d e node node 非空,打印字符串 n o d e . v a l node.val node.val,并将左右子节点加入队列
    3.若 n o d e node node 为空,打印字符串 n u l l null null
  4. 返回值:以","作为分隔拼接列表,首尾添加中括号

反序列化Deserialize(data):

利用推导出的 n o d e node node n o d e . l e f t node.left node.left n o d e . r i g h t node.right node.right在序列化列表中的位置关系,反推出各节点在序列中的索引。

  1. 特例处理:若 d a t a data data 为空,直接返回 n u l l null null
  2. 初始化:序列化列表 v a l s vals vals, 指针i = 1,根节点 r o o t root root(值设为vals[0]),包含根节点的队列 q u e u e queue queue
  3. 按层构建二叉树,当 q u e u e queue queue 为空时跳出:
    1.节点出队,记为 n o d e node node
    2.构建 n o d e node node 的左子节点 n o d e . l e f t node.left node.left,值为 vals[i],并将 n o d e . l e f t node.left node.left 入队,指针 i 后移一位;
    3.构建 n o d e node node 的右子节点 n o d e . r i g h t node.right node.right,值为 vals[i],并将 n o d e . r i g h t node.right node.right 入队,指针 i 后移一位。
  4. 返回值:根节点 r o o t root root

具体代码

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null)return "[]";
        StringBuilder res = new StringBuilder("[");//结果列表初始化
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);//队列初始化
        //层序遍历
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();//节点出队
            //若当前节点非空
            if(node != null){
                res.append(node.val+",");//打印node.val
                //左右子节点入队
                queue.offer(node.left);
                queue.offer(node.right);
            }else{//当前节点为null
                res.append("null,");
            }
        }
        res.deleteCharAt(res.length() - 1);//删除最后多余的","
        res.append("]");//尾部添加"]"
        return res.toString();//返回此序列中数据的字符串表示形式
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.equals("[]"))return null;
        //序列化列表初始化(去掉"[]",并将","作为分隔符进行字符串分解)
        String[] vals = data.substring(1, data.length() - 1).split(",");
        TreeNode root = new TreeNode(Integer.parseInt(vals[0]));//创建根节点(要先将字符串转换为int型数)
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);//队列初始化
        int i = 1;//指针初始化(从1开始是因为vals[0]对应的是根节点)
        //按层构建二叉树
        while(!queue.isEmpty()){
            TreeNode node = queue.poll();//节点出队
            if(!vals[i].equals("null")){
                node.left = new TreeNode(Integer.parseInt(vals[i]));//构建左子节点
                queue.offer(node.left);//左子节点入队
            }
            i++;//指针i后移一位(无论vals[i]是否为"null"指针都要后移)
            if(!vals[i].equals("null")){
                node.right = new TreeNode(Integer.parseInt(vals[i]));//构建右子节点
                queue.offer(node.right);//右子节点入队
            }
            i++;
        }
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

复杂度分析

序列化函数:

  • 时间复杂度: O ( n ) O(n) O(n),n 为二叉树的节点数,层序遍历需要访问所有节点,最坏情况下需要访问 n + 1 个 null,总体复杂度为 O ( 2 n + 1 ) = O ( n ) O(2n+1)=O(n) O(2n+1)=O(n)
  • 空间复杂度: O ( n ) O(n) O(n),最坏情况下队列会同时存储 n + 1 2 \frac{n+1}{2} 2n+1 个节点,占用 O ( n ) O(n) O(n)

反序列化函数:

  • 时间复杂度: O ( n ) O(n) O(n),n 为二叉树的节点数,按层构建二叉树需要遍历整个 v a l s vals vals,长度最大为 2n + 1
  • 空间复杂度:最坏情况下队列会同时存储 n + 1 2 \frac{n+1}{2} 2n+1 个节点,占用 O ( n ) O(n) O(n)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值