[LeetCode] 297. Serialization and deserialization of binary tree

Posted by spudly on Sat, 20 Jun 2020 09:23:08 +0200

subject

Link:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/

Problem Description:

analysis

Method 1: DFS (recursive)

Recursion can be understood as: transferring responsibility

  • Recurse a tree and only focus on the current single node
  • Leave the rest to recursion
    • "Serialize function, can you help me serialize my left and right subtrees? I'll wait for your return and add it to me. "
  • Why to choose preamble traversal? When deserializing, the root is left and right, which makes it easier to locate the root node value
  • When a null node is encountered, it needs to be translated into a special symbol. Only when deserializing can we know the corresponding null node here

Serialization code

const serialize = (root) => {
  if (root == null) return 'X,' // null node encountered
  const leftSerialized = serialize(root.left)   //Serialization string of left subtree
  const rightSerialized = serialize(root.right) //Serialized string of right subtree
  return root.val + ',' + leftSerialized + rightSerialized // Root left right
}

Deserialization -- also recursion

Serialization is a pre order traversal, so the serialization string presents the following arrangement:
"Root | (root | (root |, left |, right) | (root | (root |, left |, right) | (root |, left |, right) |"

The function of building tree

  • The "status" received by buildTree is a list array, which is converted from a serialized string to
  • Follow the sequence of traversal: first build the root node, then the left subtree, then the right subtree
  • The first item of the list array is the root node of the current subtree. Pop it up and build it first

buildTree pays attention to the current node, and then transfers the responsibility

  • Pop up the first item of the list array and examine it
  • If it is' X ', it returns null directly, and there is no subtree to build
  • If it's not 'X', create a node for it and build a subtree
  • Recursively call buildTree to build the left subtree
  • Recursively call buildTree to build right subtree
  • The subtree with node as the root node is constructed and returns upward

Deserialization code

const buildTree = (list) => {        // dfs function
  const nodeVal = list.shift()       // Nodes of current investigation
  if (nodeVal == 'X') return null    // Yes X, return null to the parent call
  const node = new TreeNode(nodeVal) // Create node node
  node.left = buildTree(list)        // Building the left subtree of a node
  node.right = buildTree(list)       // Constructing the right subtree of a node
  return node                        // Return the subtree with node as root node to parent call
}
const deserialize = (data) => {
  const list = data.split(',')       // Convert to list array
  return buildTree(list)             // Building trees, entry to dfs
}

Complete implementation:

public class Codec {
    public String rserialize(TreeNode root, String str) {
        if (root == null) {
            str += "None,";
        } else {
            str += str.valueOf(root.val) + ",";
            str = rserialize(root.left, str);
            str = rserialize(root.right, str);
        }
        return str;
    }
  
    public String serialize(TreeNode root) {
        return rserialize(root, "");
    }
  
    public TreeNode rdeserialize(List<String> l) {
        if (l.get(0).equals("None")) {
            l.remove(0);
            return null;
        }
  
        TreeNode root = new TreeNode(Integer.valueOf(l.get(0)));
        l.remove(0);
        root.left = rdeserialize(l);
        root.right = rdeserialize(l);
    
        return root;
    }
  
    public TreeNode deserialize(String data) {
        String[] data_array = data.split(",");
        List<String> data_list = new LinkedList<String>(Arrays.asList(data_array));
        return rdeserialize(data_list);
    }
};

Method 2: BFS

Serialization - standard BFS

  • I want null to be listed as a real node. It has a corresponding "X", but no child nodes are listed
    Investigate the listed nodes
  • If it is not null, its value is pushed into the res array and its left and right child nodes are listed
  • If null, push 'X' into res array
  • List List Until the queue is empty, all nodes are traversed, and the res array is constructed, and converted into a string

Serialization code

const serialize = (root) => {
  const queue = [root]
  let res = []
  while (queue.length) {
    const node = queue.shift()
    if (node) { // Listed nodes bring out children to be listed
      res.push(node.val)
      queue.push(node.left) // Whether it is a null node or not
      queue.push(node.right)
    } else {
      res.push('X')
    }
  }
  return res.join(',')
}

Deserialization -- also BFS: parent node is listed, child node is listed

The following figure shows the serialization string obtained by BFS:

  • Except for the first ROOT value, other node values are paired, corresponding to left and right child nodes respectively
  • Let's start with the second term and look at two node values at a time
  • The node built first is the father of the node built later. Use a queue to temporarily store it
  • The queue is initially placed in the ROOT. List the parent node and find the child node

At the same time, the parent node and two child node values are examined

  • The listed parent node, which corresponds to the left child node value pointed by the pointer and the right child node value to the right of the pointer

  • If the child value is not 'X', create a node for it, identify the parent, and list it as a future parent

  • If the child node value is' X ', do nothing (the parent node already has a null child node)

  • All parent nodes (real nodes) will walk once in the queue

Deserialization Code:

const deserialize = (data) => {
  if (data == 'X') return null       // Only one 'X', only one null
  const list = data.split(',')       // Serialized string to list array
  const root = new TreeNode(list[0]) //The first item is the root node value, create a node for it
  const queue = [root] // Put it into root initially, and make an investigation later
  let cursor = 1       // Traverse from the second item in the list
  while (cursor < list.length) {      // Pointer out of bounds
    const node = queue.shift()        // Parent node inspection
    const leftVal = list[cursor]      // Get left child value
    const rightVal = list[cursor + 1] // Get the value of the right child node
    if (leftVal !== 'X') {   // Left child value is valid
      const leftNode = new TreeNode(leftVal) // Create node
      node.left = leftNode   // Becomes the left child of the current dequeue node
      queue.push(leftNode)   // It's the father of the future, listed for inspection
    }
    if (rightVal !== 'X') {  // The right child value is a valid value
      const rightNode = new TreeNode(rightVal) // Create node
      node.right = rightNode // Becomes the right child of the current dequeue node
      queue.push(rightNode)  // It's the father of the future. It's on the list
    }
    cursor += 2              // Pointer forward 2 bits
  }
  return root // Return to root node
}

Complete implementation:

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.add(root);
        while(!queue.isEmpty()){
            TreeNode cur=queue.poll();
            if(cur==null){
                res.append("null,");
            }
            else{
               res.append(String.valueOf(cur.val));
               res.append(",");
               queue.offer(cur.left);
               queue.offer(cur.right);
            }
        }
        
        return res.toString();

        
    }


    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if(data.equals("")){
            return null;
        }
        String []temp=data.split(",");
        TreeNode root=new TreeNode(Integer.valueOf(temp[0]));
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        TreeNode cur=root;
        
        for(int i=1;i<temp.length;){
            cur=queue.poll();
            if(!temp[i].equals("null")){
                cur.left=new TreeNode(Integer.valueOf(temp[i]));
                queue.offer(cur.left);

            }
            i+=1;
            if(!temp[i].equals("null")){
                cur.right=new TreeNode(Integer.valueOf(temp[i]));
                queue.offer(cur.right);
            }
            i+=1;
        }
        return root;
    }
}

);

        }
        i+=1;
        if(!temp[i].equals("null")){
            cur.right=new TreeNode(Integer.valueOf(temp[i]));
            queue.offer(cur.right);
        }
        i+=1;
    }
    return root;
}

}

Topics: codec REST