297. Serialize and Deserialize Binary Tree
Problem Description
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.
Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Example 1:
Input: root = [1,2,3,null,null,4,5]
Output: [1,2,3,null,null,4,5]
Example 2:
Input: root = []
Output: []
Constraints:
- The number of nodes in the tree is in the range
[0, 10⁴] -1000 <= Node.val <= 1000
Solution
Python Solution
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.
:type root: TreeNode
:rtype: str
"""
if not root:
return "null"
return str(root.val) + "," + self.serialize(root.left) + "," + self.serialize(root.right)
def deserialize(self, data):
"""Decodes your encoded data to tree.
:type data: str
:rtype: TreeNode
"""
def dfs():
val = next(values)
if val == "null":
return None
node = TreeNode(int(val))
node.left = dfs()
node.right = dfs()
return node
values = iter(data.split(","))
return dfs()
Time Complexity: O(n)
Need to visit each node once for both serialization and deserialization.
Space Complexity: O(n)
Need to store the string representation of the tree.
Java Solution
/**
* 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 "null";
}
return root.val + "," + serialize(root.left) + "," + serialize(root.right);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
Queue queue = new LinkedList<>(Arrays.asList(data.split(",")));
return deserializeHelper(queue);
}
private TreeNode deserializeHelper(Queue queue) {
String val = queue.poll();
if (val.equals("null")) {
return null;
}
TreeNode node = new TreeNode(Integer.parseInt(val));
node.left = deserializeHelper(queue);
node.right = deserializeHelper(queue);
return node;
}
}
Time Complexity: O(n)
Need to visit each node once for both serialization and deserialization.
Space Complexity: O(n)
Need to store the string representation of the tree.
C++ Solution
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
if (!root) {
return "null";
}
return to_string(root->val) + "," + serialize(root->left) + "," + serialize(root->right);
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
stringstream ss(data);
string item;
queue q;
while (getline(ss, item, ',')) {
q.push(item);
}
return deserializeHelper(q);
}
private:
TreeNode* deserializeHelper(queue& q) {
string val = q.front();
q.pop();
if (val == "null") {
return nullptr;
}
TreeNode* node = new TreeNode(stoi(val));
node->left = deserializeHelper(q);
node->right = deserializeHelper(q);
return node;
}
};
Time Complexity: O(n)
Need to visit each node once for both serialization and deserialization.
Space Complexity: O(n)
Need to store the string representation of the tree.
JavaScript Solution
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* Encodes a tree to a single string.
*
* @param {TreeNode} root
* @return {string}
*/
var serialize = function(root) {
if (!root) {
return "null";
}
return root.val + "," + serialize(root.left) + "," + serialize(root.right);
};
/**
* Decodes your encoded data to tree.
*
* @param {string} data
* @return {TreeNode}
*/
var deserialize = function(data) {
const values = data.split(",");
let index = 0;
function dfs() {
const val = values[index++];
if (val === "null") {
return null;
}
const node = new TreeNode(parseInt(val));
node.left = dfs();
node.right = dfs();
return node;
}
return dfs();
};
Time Complexity: O(n)
Need to visit each node once for both serialization and deserialization.
Space Complexity: O(n)
Need to store the string representation of the tree.
C# Solution
/**
* Definition for a binary tree node.
* public class TreeNode {
* public int val;
* public TreeNode left;
* public TreeNode right;
* public TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public string serialize(TreeNode root) {
if (root == null) {
return "null";
}
return root.val + "," + serialize(root.left) + "," + serialize(root.right);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(string data) {
Queue queue = new Queue(data.Split(','));
return deserializeHelper(queue);
}
private TreeNode deserializeHelper(Queue queue) {
string val = queue.Dequeue();
if (val == "null") {
return null;
}
TreeNode node = new TreeNode(int.Parse(val));
node.left = deserializeHelper(queue);
node.right = deserializeHelper(queue);
return node;
}
}
Time Complexity: O(n)
Need to visit each node once for both serialization and deserialization.
Space Complexity: O(n)
Need to store the string representation of the tree.
Approach Explanation
The solution uses preorder traversal for serialization and deserialization:
- Key Insight:
- Use preorder traversal (root, left, right)
- Mark null nodes explicitly
- Use comma as delimiter
- Reconstruct using recursion
- Serialization Steps:
- Handle null case
- Convert root value to string
- Recursively serialize left
- Recursively serialize right
Example walkthrough:
- Tree: [1,2,3,null,null,4,5]
- Serialized: "1,2,null,null,3,4,null,null,5,null,null"
- Deserialization rebuilds tree
- Uses queue/iterator for values
Alternative approaches:
- Level order traversal
- JSON serialization
- Binary serialization
- Custom encoding schemes
Edge Cases:
- Empty tree
- Single node tree
- Unbalanced tree
- Full binary tree