> ## Documentation Index
> Fetch the complete documentation index at: https://leetcode-py.wisl.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> leetcode-py is a Python LeetCode practice environment generator with one CLI: lcpy. It is not a service or platform.
> Each problem is a directory under leetcode/ with README.md, solution.py, test_solution.py, helpers.py, and playground.ipynb. lcpy gen creates them from JSON templates bundled with the package.
> Examples are backed by tests; copy them verbatim.

# Serialize and Deserialize Binary Tree

> Tested Python solution for LeetCode 297 with 15 pytest cases. Generate a practice environment with lcpy.

LeetCode 297, Hard. Topics: String, Tree, Depth-First Search, Breadth-First Search, Design, Binary Tree. [View on LeetCode](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/description/).

Generate this problem as a practice environment: tested reference solution, 15 [parametrized pytest cases](/practice/testing), and a playground notebook:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
lcpy gen -n 297   # by problem number
lcpy gen -s serialize_and_deserialize_binary_tree   # by problem name
```

## Problem

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.

### Examples

![Example 1](https://assets.leetcode.com/uploads/2020/09/15/serdeser.jpg)

```
Input: root = [1,2,3,null,null,4,5]
Output: [1,2,3,null,null,4,5]
```

```
Input: root = []
Output: []
```

### Constraints

* The number of nodes in the tree is in the range \[0, 10^4].
* -1000 \<= Node.val \<= 1000

## Solution

Reference implementation from [solution.py on GitHub](https://github.com/wislertt/leetcode-py/blob/main/leetcode/serialize_and_deserialize_binary_tree/solution.py), full suite in [test\_solution.py](https://github.com/wislertt/leetcode-py/blob/main/leetcode/serialize_and_deserialize_binary_tree/test_solution.py):

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from leetcode_py import TreeNode


class Codec:
    # Preorder with Null Markers
    # Time: O(n)
    # Space: O(n)
    def __init__(self) -> None:
        pass

    # Time: O(n)
    # Space: O(n)
    def serialize(self, root: TreeNode[int] | None) -> str:
        vals = []

        def dfs(node: TreeNode[int] | None):
            if not node:
                vals.append("#")
                return
            vals.append(str(node.val))
            dfs(node.left)
            dfs(node.right)

        dfs(root)
        return ",".join(vals)

    # Time: O(n)
    # Space: O(n)
    def deserialize(self, data: str) -> TreeNode[int] | None:
        vals = iter(data.split(","))

        def dfs():
            val = next(vals)
            if val == "#":
                return None
            node = TreeNode[int](int(val))
            node.left = dfs()
            node.right = dfs()
            return node

        return dfs()


# Binary Tree Serialization Techniques

# Example Tree:
#       1
#      / \
#     2   3
#        / \
#       4   5

# 1. Preorder with Null Markers (This Implementation)
# Visit: root → left → right, mark nulls with '#'
# Result: "1,2,#,#,3,4,#,#,5,#,#"
# Pros: Self-contained, unambiguous, O(n) reconstruction
# Cons: Longer string due to null markers

# 2. Level-order (BFS) with Null Markers
# Visit level by level, mark nulls with '#'
# Result: "1,2,3,#,#,4,5"
# Pros: Simple format like preorder, level-by-level intuitive
# Cons: Still requires queue processing

# 3. Postorder with Null Markers
# Visit: left → right → root
# Result: "#,#,2,#,#,4,#,#,5,3,1"
# Pros: Bottom-up reconstruction
# Cons: Less intuitive than preorder

# 4. Inorder + Preorder (Two Arrays)
# Inorder: [2,1,4,3,5], Preorder: [1,2,3,4,5]
# Pros: Works for any binary tree structure
# Cons: Requires two arrays, only works with unique values

# 5. Parenthetical Preorder
# Same traversal as #1 but with parentheses format: value(left)(right)
# Result: "1(2()())(3(4()())(5()()))"
# Pros: Human readable structure, shows nesting clearly
# Cons: Complex parsing, verbose

# 6. Parenthetical Postorder
# Same traversal as #3 but with parentheses format: (left)(right)value
# Result: "(()()2)((()()4)(()()5)3)1"
# Pros: Bottom-up readable structure
# Cons: Even more complex parsing
```

## Complexity

| Time | Space |
| ---- | ----- |
| O(n) | O(n)  |

## Tags

[Grind 75](/catalog/grind-75), [Grind](/catalog/grind), [Blind 75](/catalog/blind-75), [NeetCode 150](/catalog/neetcode-150), [NeetCode 250](/catalog/neetcode-250), [NeetCode All](/catalog/neetcode), [AlgoMaster 75](/catalog/algo-master-75).
