Design an algorithm to serialize and deserialize a binary tree. 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. The algorithm should serialize a binary tree to a string, and this string can be deserialized to the original tree structure. There are no restrictions on how the algorithm should work. Consider these examples:
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:
[0, 10^4]
.-1000 <= Node.val <= 1000
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.
## Serialize and Deserialize a Binary Tree
### Problem Description
The problem requires designing an algorithm to serialize a binary tree into a string representation and subsequently deserialize the string back into the original binary tree structure. The serialization and deserialization process must preserve the structure and content of the original binary tree.
**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: []
### Naive Approach (Breadth-First Search)
A simple way to serialize and deserialize a binary tree is by performing a breadth-first search (BFS). During serialization, we traverse the tree level by level, adding each node's value to a list. If a node is `null`, we add a special marker (e.g., "null") to the list. During deserialization, we reconstruct the tree from the list, level by level.
#### Code (Python)
```python
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Codec:
def serialize(self, root):
if not root:
return "[]"
queue = [root]
result = []
while queue:
node = queue.pop(0)
if node:
result.append(str(node.val))
queue.append(node.left)
queue.append(node.right)
else:
result.append("null")
# Remove trailing nulls
while result and result[-1] == "null":
result.pop()
return '[' + ','.join(result) + ']'
def deserialize(self, data):
if data == "[]":
return None
data = data[1:-1].split(',')
root = TreeNode(int(data[0]))
queue = [root]
i = 1
while queue:
node = queue.pop(0)
if i < len(data) and data[i] != "null":
node.left = TreeNode(int(data[i]))
queue.append(node.left)
i += 1
if i < len(data) and data[i] != "null":
node.right = TreeNode(int(data[i]))
queue.append(node.right)
i += 1
return root
Another approach is to use preorder traversal. We can serialize the tree by visiting the root first, then the left subtree, and then the right subtree. We use a special marker for null
nodes. When deserializing, we reconstruct the tree using the preorder traversal sequence.
class TreeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Codec:
def serialize(self, root):
def preorder(node):
if not node:
result.append('null')
return
result.append(str(node.val))
preorder(node.left)
preorder(node.right)
result = []
preorder(root)
return ','.join(result)
def deserialize(self, data):
def buildTree():
val = next(data_iter)
if val == 'null':
return None
node = TreeNode(int(val))
node.left = buildTree()
node.right = buildTree()
return node
data_iter = iter(data.split(','))
return buildTree()
None
.null
nodes (e.g., "null") is arbitrary. It could be any value that is not a valid node value.