• LeetCode OJ 297. Serialize and Deserialize Binary Tree


    Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

    Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

    For example, you may serialize the following tree

        1
       / 
      2   3
         / 
        4   5
    

    as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

     Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

    Credits:
    Special thanks to @Louis1992 for adding this problem and creating all test cases.

    【解析1】

    其实LeetCode上树的表示方式就挺好,即"[1,2,3,null,null,4,5]"这种形式,我们接下来就实现以下这种序列化。

    序列化比较容易,我们做一个层次遍历就好,空的地方用null表示,稍微不同的地方是题目中示例得到的结果是"[1,2,3,null,null,4,5,null,null,null,null,]",即 4 和 5 的两个空节点我们也存了下来。

    饭序列化时,我们根据都好分割得到每个节点。需要注意的是,反序列化时如何寻找父节点与子节点的对应关系,我们知道在数组中,如果满二叉树(或完全二叉树)的父节点下标是 i,那么其左右孩子的下标分别为 2*i+1 和 2*i+2,但是这里并不一定是满二叉树(或完全二叉树),所以这个对应关系需要稍作修改。如下面这个例子:

           5
          / 
         4   7
        /   /
       3   2
      /   /
     -1  9

    序列化结果为[5,4,7,3,null,2,null,-1,null,9,null,null,null,null,null,]。

    其中,节点 2 的下标是 5,可它的左孩子 9 的下标为 9,并不是 2*i+1=11,原因在于 前面有个 null 节点,这个 null 节点没有左右孩子,所以后面的节点下标都提前了2。所以我们只需要记录每个节点前有多少个 null 节点,就可以找出该节点的孩子在哪里了,其左右孩子分别为 2*(i-num)+1 和 2*(i-num)+2(num为当前节点之前 null 节点的个数)。

    【java代码】非递归

     1 /**
     2  * Definition for a binary tree node.
     3  * public class TreeNode {
     4  *     int val;
     5  *     TreeNode left;
     6  *     TreeNode right;
     7  *     TreeNode(int x) { val = x; }
     8  * }
     9  */
    10 public class Codec {
    11 
    12     // Encodes a tree to a single string.
    13     public String serialize(TreeNode root) {
    14         StringBuilder sb = new StringBuilder();  
    15         Queue<TreeNode> queue = new LinkedList<TreeNode>();  
    16         queue.offer(root);  
    17           
    18         while (!queue.isEmpty()) {  
    19             TreeNode node = queue.poll();  
    20             if (node == null) {  
    21                 sb.append("null,");  
    22             } else {  
    23                 sb.append(String.valueOf(node.val) + ",");  
    24                 queue.offer(node.left);  
    25                 queue.offer(node.right);  
    26             }  
    27         }  
    28           
    29         return sb.toString();
    30     }
    31 
    32     // Decodes your encoded data to tree.
    33     public TreeNode deserialize(String data) {
    34         if (data == null || data.isEmpty()) return null;  
    35           
    36         String[] vals = data.split(",");  
    37         int[] nums = new int[vals.length]; // 节点i之前null节点的个数  
    38         TreeNode[] nodes = new TreeNode[vals.length];  
    39           
    40         for (int i = 0; i < vals.length; i++) {   //计算每个节点前面null节点的数目
    41             if (i > 0) {  
    42                 nums[i] = nums[i - 1];  
    43             }  
    44             if (vals[i].equals("null")) {  
    45                 nodes[i] = null;  
    46                 nums[i]++;  
    47             } else {  
    48                 nodes[i] = new TreeNode(Integer.parseInt(vals[i]));  
    49             }  
    50         }  
    51           
    52         for (int i = 0; i < vals.length; i++) {  //对节点进行连接操作
    53             if (nodes[i] == null) {  
    54                 continue;  
    55             }  
    56             nodes[i].left = nodes[2 * (i - nums[i]) + 1];  
    57             nodes[i].right = nodes[2 * (i - nums[i]) + 2];  
    58         }  
    59           
    60         return nodes[0];
    61     }
    62 
    63 }

    【解析2】

    我们也可以用递归来解决这个问题:The idea is simple: print the tree in pre-order traversal and use "X" to denote null node and split node with ",". We can use a StringBuilder for building the string on the fly. For deserializing, we use a Queue to store the pre-order traversal and since we have "X" as null node, we know exactly how to where to end building subtress.

    这个思路用到的是树的前序遍历,因为序列中包含了值为null的节点,因此我们可以很容易地进行反序列化操作。

    【java代码】递归

     1 public class Codec {
     2     private static final String spliter = ",";
     3     private static final String NN = "X";
     4 
     5     // Encodes a tree to a single string.
     6     public String serialize(TreeNode root) {
     7         StringBuilder sb = new StringBuilder();
     8         buildString(root, sb);
     9         return sb.toString();
    10     }
    11 
    12     private void buildString(TreeNode node, StringBuilder sb) {
    13         if (node == null) {
    14             sb.append(NN).append(spliter);
    15         } else {
    16             sb.append(node.val).append(spliter);
    17             buildString(node.left, sb);
    18             buildString(node.right,sb);
    19         }
    20     }
    21     // Decodes your encoded data to tree.
    22     public TreeNode deserialize(String data) {
    23         Deque<String> nodes = new LinkedList<>();
    24         nodes.addAll(Arrays.asList(data.split(spliter)));
    25         return buildTree(nodes);
    26     }
    27 
    28     private TreeNode buildTree(Deque<String> nodes) {
    29         String val = nodes.remove();
    30         if (val.equals(NN)) return null;
    31         else {
    32             TreeNode node = new TreeNode(Integer.valueOf(val));
    33             node.left = buildTree(nodes);
    34             node.right = buildTree(nodes);
    35             return node;
    36         }
    37     }
    38 }
     
  • 相关阅读:
    Building Java Projects with Gradle
    Vert.x简介
    Spring及Spring Boot 国内快速开发框架
    dip vs di vs ioc
    Tools (StExBar vs Cmder)which can switch to command line window on context menu in windows OS
    SSO的定义、原理、组件及应用
    ModSecurity is an open source, cross-platform web application firewall (WAF) module.
    TDD中测试替身学习总结
    Spring事务银行转账示例
    台式机(华硕主板)前面板音频接口(耳机和麦克风)均无声的解决办法
  • 原文地址:https://www.cnblogs.com/liujinhong/p/5484776.html
Copyright © 2020-2023  润新知