[LeetCode] 297. Serialization and deserialization of binary trees

 

Table of contents

1. Introduction to the topic

2. Problem-solving ideas 

2.1. Detailed process diagram

2.2. Code description 

 2.3. Complete code


 

1. Introduction to the topic

Original question link:297. Serialization and deserialization of binary trees - LeetCode

 Example 1:

输入:root = [1,2,3,null,null,4,5]

Output:[1,2,3,null,null,4,5]

Example 2:

Import:root = [ ]

Output:[ ]

Example 3:

Import:root = [1]

Output:[1]

Example 4:

Import:root = [1,2]

Output:[1,2]

hint:

  • The number of nodes in the tree is within the range [0, 104] 
  • -1000 <= Node.val <= 1000

2. Problem-solving ideas 

Binary tree serialization is to convert the binary tree in the memory into the string form on the hard disk, and requires that each binary tree can correspond to a unique string.

Binary tree deserialization is to restore this unique string back to the corresponding binary tree in memory.

2.1. Detailed process diagram

Here we usepreorder traversal to complete the serialization. As long as you understand the serialization of one kind of traversal, the serialization of other traversals (including but not limited to in-order traversal, post-order traversal, and hierarchical traversal) will follow the same pattern.

Let’s talk about the rules first:

  • The binary tree is accessed in the order of preorder traversal. If node 1 is accessed, 1 is written into the string. Similarly for node 2, 2 is written into the node.
  • If an empty node is encountered, an identifier is stored in the string. Here I use pound sign # to express the empty node. point.
  • At the same time, two nodes need to be separated by underscore _, which can also be understood as indicating the end of a node value.

Illustration of the serialization process:

Initially the string str is empty. According to the pre-order traversal, node 1 is visited first, so at this time, 1 and the underscore _ indicating the end of the node value are stored in the string.

str[ ]= "1_"

Then the pre-order traversal accesses node 2, and continues to splice 2 and underscore_ into the string str.

str[ ]= "1_2_"

Then the empty node is accessed through pre-order traversal. At this time, the identifier symbol #underscore_ representing the stewardess point is spliced ​​into the string str.

str[ ]= "1_2_#_"

In the same way, traverse in sequence

str[ ]= "1_2_#_#_"

Finally, the str string is obtained by traversing in sequence.

str[ ]= "1_2_#_#_3_4_#_#_5_#_#_"

This str string is the serialization of the binary tree, and using the string to restore the binary tree through pre-order traversal is called deserialization.

Deserialization process diagram:

str is traversed from front to back, and restored back to the binary tree in the order of traversing [head left and right] first.

 

 

 Traverse str in sequence and finally restore the original binary tree.

 

2.2. Code description 

Use recursion to traverse the binary tree in order to generate the corresponding serialized string ret.

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if(root == null)   //等于空时返回井号标识符
        {
            return "#_";
        }
        String res = root.val + "_";  //将结点值与下划线_拼接
        res += serialize(root.left);  //将左子树返回的字符串拼接到当前的ret后
        res += serialize(root.right); //将右子树返回的字符串拼接到当前的ret后
        return ret;
    }

Use the split method to split the string, put the split values ​​into an array, and then use the queue to receive the values ​​of the array in turn.

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] val = data.split("_");  //将data字符串按照下划线_为分隔符对字符串进行拆分
        Queue<String> queue = new  LinkedList<>(); //队列
        for(int i = 0;i < val.length; i++) 
        {
            queue.add(val[i]);   //将拆分出来的值依次入队
        }
        return reconPreOrder(queue);  //返回队列
    }

The obtained queues are dequeued in sequence, and recursion is used to determine whether it is the empty identifier pound sign #. If so, null is returned. Otherwise, the value is stored in the newly opened head node root, and then the left subtree and the right subtree are created recursively. Tree. Finally, the head node root is returned, which completes the deserialization of the binary tree.

    public static TreeNode reconPreOrder(Queue<String> queue)
    {
        String val = queue.poll();   //出队
        if(val.equals("#"))   //等于#则返回null
        {
            return null;
        }
        TreeNode root = new TreeNode(Integer.valueOf(val));   //创建头结点存放val值
        root.left = reconPreOrder(queue);   //从递归中获取左子树信息
        root.right = reconPreOrder(queue);  //从递归中获取右子树信息

        return root;   //最后返回头结点
    }

 2.3. Complete code

/**
 * 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 "#_";
        }
        String res = root.val + "_";
        res += serialize(root.left);
        res += serialize(root.right);
        return res;
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] val = data.split("_");
        Queue<String> queue = new  LinkedList<>();
        for(int i = 0;i < val.length; i++)
        {
            queue.add(val[i]);
        }
        return reconPreOrder(queue);
    }

    public static TreeNode reconPreOrder(Queue<String> queue)
    {
        String val = queue.poll();
        if(val.equals("#"))
        {
            return null;
        }
        TreeNode root = new TreeNode(Integer.valueOf(val));
        root.left = reconPreOrder(queue);
        root.right = reconPreOrder(queue);

        return root;
    }
}

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

Easter eggs:

I found an interesting solution to the problem while looking at other solutions (please do not imitate it) hahahahaha

 


 

A detailed introduction to binary tree traversal:

[Algorithm and Data Structure] Three types of binary tree traversal code implementations (Part 1) - explained using recursive order knowledge points_Hacynn's blog-CSDN blogicon-default.png?t=N7T8https://blog .csdn.net/zzzzzhxxx/article/details/133609612?spm=1001.2014.3001.5502[Algorithm and Data Structure] Three types of binary tree traversal code implementations (Part 2) - non-recursive implementation ( Lots of illustrations) - CSDN Blogicon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/133669283?spm=1001.2014.3001.5502

 

If you think the author's writing is good, please give the blogger a big like and support. Your support is my biggest motivation for updating!

If you think the author's writing is good, please give the blogger a big like and support. Your support is my biggest motivation for updating!

If you think the author's writing is good, please give the blogger a big like and support. Your support is my biggest motivation for updating!

Guess you like

Origin blog.csdn.net/zzzzzhxxx/article/details/133827375