# [LeetCode] 297. Serialization and deserialization of binary tree

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

# subject

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(",");
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) //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
}
}

```

## 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();
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));
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