Serialize and Deserialize BST
MEDIUMDescription
Serialization is 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 search tree. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.
The encoded string should be as compact as possible.
Example 1:
Input: root = [2,1,3] Output: [2,1,3]
Example 2:
Input: root = [] Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 104]. 0 <= Node.val <= 104- The input tree is guaranteed to be a binary search tree.
Approaches
Checkout 2 different approaches to solve Serialize and Deserialize BST. Click on different approaches to view the approach and algorithm in detail.
Pre-order Traversal with Null Markers
This approach treats the Binary Search Tree as a general Binary Tree. It serializes the tree using a pre-order traversal, explicitly storing null children with a special marker (e.g., 'N' or '#'). This ensures that the structure can be perfectly reconstructed, but it doesn't take advantage of the BST properties, leading to a less compact string as requested by the problem.
Algorithm
- Serialization:
- Define a recursive function
serializeHelper(node, stringBuilder). - If
nodeisnull, append a null marker (e.g., "N") and a separator to thestringBuilderand return. - Otherwise, append the
node.valand a separator. - Recursively call
serializeHelperfor the left child. - Recursively call
serializeHelperfor the right child.
- Define a recursive function
- Deserialization:
- Split the input string by the separator into a queue of strings.
- Define a recursive function
deserializeHelper(queue). - Dequeue a value from the queue.
- If the value is the null marker, return
null. - Otherwise, create a new
TreeNodewith the parsed value. - Set the node's left child by recursively calling
deserializeHelper(queue). - Set the node's right child by recursively calling
deserializeHelper(queue). - Return the created node.
Serialization
A recursive Depth-First Search (DFS) function, specifically pre-order, is used. The function traverses the tree in the order: root -> left -> right. When a non-null node is encountered, its value is appended to a string builder, followed by a delimiter. When a null pointer is encountered (an empty child), a special marker (e.g., "N") is appended. This process creates a string that uniquely represents the tree structure, including its empty branches.
Deserialization
The serialized string is first split by the delimiter into a list of values. A queue is a natural choice to process these values in the order they were generated. A recursive helper function builds the tree. It dequeues the next value. If the value is the null marker, it returns null. Otherwise, it creates a new node with the parsed integer value. It then recursively calls itself to build the left subtree and then the right subtree, perfectly reconstructing the original tree.
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
public class Codec {
private static final String SEP = ",";
private static final String NULL = "N";
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
serializeHelper(root, sb);
return sb.toString();
}
private void serializeHelper(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append(NULL).append(SEP);
return;
}
sb.append(node.val).append(SEP);
serializeHelper(node.left, sb);
serializeHelper(node.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.isEmpty()) {
return null;
}
Queue<String> nodes = new LinkedList<>(Arrays.asList(data.split(SEP)));
return deserializeHelper(nodes);
}
private TreeNode deserializeHelper(Queue<String> nodes) {
String val = nodes.poll();
if (val.equals(NULL)) {
return null;
}
TreeNode node = new TreeNode(Integer.parseInt(val));
node.left = deserializeHelper(nodes);
node.right = deserializeHelper(nodes);
return node;
}
}
Complexity Analysis
Pros and Cons
- Simple to implement and understand.
- Works for any binary tree, not just BSTs.
- The serialized string is not compact because it stores redundant null markers.
- Does not leverage the properties of a BST for optimization.
Code Solutions
Checking out 3 solutions in different languages for Serialize and Deserialize BST. Click on different languages to view the code.
Video Solution
Watch the video walkthrough for Serialize and Deserialize BST
Similar Questions
5 related questions you might find useful
Algorithms:
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.