序列化二叉树

一、需求

  • 请实现两个函数,分别用来序列化和反序列化二叉树。
示例: 

你可以将以下二叉树:

    1
   / \
  2   3
     / \
    4   5

序列化为 "[1,2,3,null,null,4,5]"

二、层序遍历BFS

2.1  思路分析

  1. 题目要求的"序列化"和"反序列化"是可逆操作。因此,序列化的字符串应该携带"完整的"二叉树信息,即拥有单独表示二叉树的能力。
  2. 为使反序列化可行,考虑将越过叶节点的null也看作节点。如果是这样,对于列表中任意结点node,其左子结点node.left和右子结点node.right在序列中的位置是唯一确定的。
  3. 设m为列表区间[0,n]中空节点(即null)的个数,则可总结出node、node.left、node.right在列表索引中的对应关系:

2.2.1  序列化serialize

  1. 特例处理:若root为空,则直接返回空列表"[ ]";
  2. 初始化:队列queue(包含根节点root);序列化列表res;
  3. 层序遍历:当queue为空时跳出

         1.节点出队,记为node;

         2.若node不为空,打印字符串node.val,将左、右子节点加入到queue;

         3.若node为空,则打印字符串"null";

      4.返回值:拼接列表(用‘,’隔开,首尾添加中括号)。

2.2.2  序列化代码实现

public String serialize(TreeNode root) {
        if(root == null) return "[]";
        StringBuilder res = new StringBuilder("[");
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.add(root);
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(node != null) {
                res.append(node.val+",");
                queue.add(node.left);
                queue.add(node.right);
            } else {
                res.append("null,");
            }
        }
        res.deleteCharAt(res.length()-1);
        res.append("]");
        return res.toString();
    }

2.2.3  复杂度分析

  • 时间复杂度为O(N),假设二叉树有N个节点,最坏情况下,二叉树退化为链表,需要遍历N个节点和N+1个null,因此时间复杂度为O(2N+1),即O(N);
  • 空间复杂度为O(N),当二叉树为满二叉树时,队列最多存储(N+1)/2个元素,因此空间复杂度为O(N)。

2.3.1  反序列化deserialize

  1. 特例处理:若data为空,直接返回null;
  2. 初始化:序列化列表vals(先去掉首尾中括号,再用逗号隔开),指针i = i,根节点root( 值为vals[0] ),队列queue(包含root);
  3. 按层构建:当queue为空时跳出

         1.节点出队,记为node;

         2.构建node的左子节点:node.left的值为vals[i],并将node.left入队;

         3.执行i += 1;

         4.构建node的右子节点:node.right的值为vals[i],并将node.right入队;

         5.执行i += 1;

      4.返回值:返回根节点root即可。

2.3.2  反序列化代码实现

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]));
        Queue<TreeNode> queue = new LinkedList<>() {{add(root);}};
        int i = 1;
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(!vals[i].equals("null")) {
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.left);
            }
            i++;
            if(!vals[i].equals("null")) {
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.right);
            }
            i++;
        }
        return root;
    }

2.3.3  复杂度分析

  • 时间复杂度为O(N),N为二叉树的节点个数,按层构建二叉树需要遍历整个vals,其长度最大为2N+1;
  • 空间复杂度为O(N),最差情况下,队列queue最多同时存储(N+1)/2个元素,因此使用O(N)的额外空间。 

三、完整代码

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<TreeNode>();
        queue.add(root);
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(node != null) {
                res.append(node.val+",");
                queue.add(node.left);
                queue.add(node.right);
            } else {
                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]));
        Queue<TreeNode> queue = new LinkedList<>() {{add(root);}};
        int i = 1;
        while(!queue.isEmpty()) {
            TreeNode node = queue.poll();
            if(!vals[i].equals("null")) {
                node.left = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.left);
            }
            i++;
            if(!vals[i].equals("null")) {
                node.right = new TreeNode(Integer.parseInt(vals[i]));
                queue.add(node.right);
            }
            i++;
        }
        return root;
    }
}

四、参考地址

作者:jyd

链接:https://leetcode-cn.com/problems/xu-lie-hua-er-cha-shu-lcof/solution/mian-shi-ti-37-xu-lie-hua-er-cha-shu-ceng-xu-bian-/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值