Talentd
FleetCode
Make and follow sheets.Sign in

Serialize and Deserialize N-ary Tree solution and explanation

HardBreadth-First SearchDepth-First SearchStringTree5 min read68.7% acceptanceUpdated 1 Sept 2026Premium elsewhere, free here
[Java] Leetcode 428. Serialize and Deserialize N-ary Tree [N-ary Tree #1]Eric Programming · 14:06 · 5K viewsWatch on YouTube
7 more videos on this problem
  1. [Java] Leetcode 428. Serialize and Deserialize N-ary Tree [N-ary Tree #1]Eric Programming · 14:06 · 5K views
  2. Serialize and Deserialize N ary Tree LeetCode 2018 12 25Vivek Sharma · 13:20 · 3K views
  3. Serialize and Deserialize N-ary Tree: Leetcode 428Tony Teaches · 18:37 · 2K views
  4. Leetcode 428. Serialize and Deserialize N-Ary Tree Explained using DFS pre-order traversalInterviewDose · 5:11 · 1K views
  5. Serialize and Deserialize N-ary Tree (Hard) | Premium | Top 52 Uber LeetCode Coding QuestionsAakash Verma · 25:18 · 860 views
  6. [BFS] Serialize and Deserialize N-ary Tree (Hard) | Premium | Top 52 Uber LeetCode Coding QuestionsAakash Verma · 29:17 · 618 views
  7. 428. Serialize and Deserialize N-ary Tree (Leetcode Hard)Programming Live with Larry · 14:21 · 455 views
  8. Serailize and Deserialize N-Ary Tree | Leetcode SolutionPepcoding · 24:27 · 5K views

The 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 an N-ary tree. An N-ary tree is a rooted tree in which each node has no more than N children. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that an N-ary tree can be serialized to a string and this string can be deserialized to the original tree structure.

For example, you may serialize the following 3-ary tree

as [1 [3[5 6] 2 4]]. Note that this is just an example, you do not necessarily need to follow this format.

Or you can follow LeetCode's level order traversal serialization format, where each group of children is separated by the null value.

For example, the above tree may be serialized as [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14].

You do not necessarily need to follow the above-suggested formats, there are many more different formats that work so please be creative and come up with different approaches yourself.

Example 1:

Input: root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
Output: [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]

Example 2:

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

Example 3:

Input: root = []
Output: []

Constraints:

  • The number of nodes in the tree is in the range [0, 104].
  • 0 <= Node.val <= 104
  • The height of the n-ary tree is less than or equal to 1000
  • Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.

Approach overview

Problem Overview: You need to convert an N-ary tree into a string so it can be stored or transmitted, and then reconstruct the exact same tree from that string. The structure must remain identical: node values and parent‑child relationships must be preserved.

Approach 1: DFS Preorder Serialization with Child Count (O(n) time, O(n) space)

The common solution uses preorder traversal from Depth-First Search. For each node, store its value followed by the number of children. During serialization, recursively visit nodes and append value, childCount to a string or list. During deserialization, read tokens sequentially: create a node, then recursively build the next childCount children. The key insight is that the child count completely defines the tree structure, so the parser always knows how many recursive calls to make.

This approach processes each node exactly once, giving O(n) time complexity. The serialized output stores two tokens per node (value and child count), so the storage cost is also O(n). Recursive calls use up to O(h) stack space where h is the tree height.

Approach 2: BFS Level Order Serialization (O(n) time, O(n) space)

A second option uses Breadth-First Search with a queue. Serialize nodes level by level. For each node, record its value and the number of children, then enqueue all children. Deserialization mirrors this process: read the root first, push it into a queue, then reconstruct children for each node based on the stored child count.

This approach still visits each node once, so the runtime remains O(n). The queue may hold up to an entire level of nodes, leading to O(w) auxiliary space where w is the maximum width of the tree. The serialized string size remains linear in the number of nodes.

Both strategies rely on representing structure explicitly. Without storing the number of children (or equivalent delimiters), reconstructing the tree would be ambiguous. The serialized format is essentially a compact structural encoding of the tree.

Recommended for interviews: DFS preorder with child counts is the most common implementation. It produces a compact representation and maps naturally to recursive deserialization. Showing the BFS alternative demonstrates deeper understanding, but the DFS version is typically what interviewers expect because it is simpler to implement correctly.

Solution

We can serialize an N-ary tree with level order traversal. Start from the root, append its value, and enqueue it. Each time we dequeue a node, we append the values of all its children and enqueue them, then append a special character # to mark the end of that node's children. Finally we join the values with commas.

During deserialization, we split the string by the delimiter. Create the root from the first value and enqueue it. For each dequeued node, keep reading the following values as its children until we meet #.

The time complexity is O(n), and the space complexity is O(n), where n is the number of nodes in the N-ary tree.

"""
# Definition for a Node.
class Node(object):
    def __init__(self, val: Optional[int] = None, children: Optional[List['Node']] = None):
        self.val = val
        self.children = children
"""


class Codec:
    def serialize(self, root: 'Node') -> str:
        if root is None:
            return ''
        ans = [str(root.val)]
        q = deque([root])
        while q:
            node = q.popleft()
            for child in node.children or []:
                ans.append(str(child.val))
                q.append(child)
            ans.append('#')
        return ','.join(ans)

    def deserialize(self, data: str) -> 'Node':
        if not data:
            return None
        vals = data.split(',')
        root = Node(int(vals[0]), [])
        q = deque([root])
        i = 1
        while q:
            node = q.popleft()
            while vals[i] != '#':
                child = Node(int(vals[i]), [])
                node.children.append(child)
                q.append(child)
                i += 1
            i += 1
        return root


# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))
/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Codec {
    public String serialize(Node root) {
        if (root == null) {
            return "";
        }
        List<String> ans = new ArrayList<>();
        Deque<Node> q = new ArrayDeque<>();
        ans.add(String.valueOf(root.val));
        q.offer(root);
        while (!q.isEmpty()) {
            Node node = q.poll();
            if (node.children != null) {
                for (Node child : node.children) {
                    ans.add(String.valueOf(child.val));
                    q.offer(child);
                }
            }
            ans.add("#");
        }
        return String.join(",", ans);
    }

    public Node deserialize(String data) {
        if ("".equals(data)) {
            return null;
        }
        String[] vals = data.split(",");
        Node root = new Node(Integer.parseInt(vals[0]), new ArrayList<>());
        Deque<Node> q = new ArrayDeque<>();
        q.offer(root);
        int i = 1;
        while (!q.isEmpty()) {
            Node node = q.poll();
            while (!"#".equals(vals[i])) {
                Node child = new Node(Integer.parseInt(vals[i++]), new ArrayList<>());
                node.children.add(child);
                q.offer(child);
            }
            ++i;
        }
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Codec {
public:
    string serialize(Node* root) {
        if (!root) {
            return "";
        }
        queue<Node*> q{{root}};
        string ans = to_string(root->val);
        while (!q.empty()) {
            auto node = q.front();
            q.pop();
            for (auto child : node->children) {
                ans += "," + to_string(child->val);
                q.push(child);
            }
            ans += ",#";
        }
        return ans;
    }

    Node* deserialize(string data) {
        if (data.empty()) {
            return nullptr;
        }
        stringstream ss(data);
        string t;
        getline(ss, t, ',');
        Node* root = new Node(stoi(t), {});
        queue<Node*> q{{root}};
        while (!q.empty()) {
            auto node = q.front();
            q.pop();
            while (getline(ss, t, ',') && t != "#") {
                Node* child = new Node(stoi(t), {});
                node->children.push_back(child);
                q.push(child);
            }
        }
        return root;
    }
};

// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
/**
 * Definition for a Node.
 * type Node struct {
 *     Val int
 *     Children []*Node
 * }
 */

type Codec struct {
}

func Constructor() *Codec {
	return &Codec{}
}

func (this *Codec) serialize(root *Node) string {
	if root == nil {
		return ""
	}
	ans := []string{strconv.Itoa(root.Val)}
	q := []*Node{root}
	for len(q) > 0 {
		node := q[0]
		q = q[1:]
		for _, child := range node.Children {
			ans = append(ans, strconv.Itoa(child.Val))
			q = append(q, child)
		}
		ans = append(ans, "#")
	}
	return strings.Join(ans, ",")
}

func (this *Codec) deserialize(data string) *Node {
	if data == "" {
		return nil
	}
	vals := strings.Split(data, ",")
	v, _ := strconv.Atoi(vals[0])
	root := &Node{Val: v}
	q := []*Node{root}
	i := 1
	for len(q) > 0 {
		node := q[0]
		q = q[1:]
		for i < len(vals) && vals[i] != "#" {
			v, _ = strconv.Atoi(vals[i])
			child := &Node{Val: v}
			node.Children = append(node.Children, child)
			q = append(q, child)
			i++
		}
		i++
	}
	return root
}

/**
 * Your Codec object will be instantiated and called as such:
 * obj := Constructor();
 * data := obj.serialize(root);
 * ans := obj.deserialize(data);
 */
Try this approach in the editor

Complexity analysis

ApproachTimeSpaceWhen to Use
DFS Preorder with Child CountO(n)O(n)Most common interview solution; simple recursive structure
BFS Level Order SerializationO(n)O(n)Useful when you prefer iterative logic with queues
DFS with Delimiter MarkersO(n)O(n)Alternative format using sentinel markers instead of child counts

Frequently asked questions

Is Serialize and Deserialize N-ary Tree easy or hard?

The problem is rated Hard because it combines tree traversal with designing a reliable encoding format. The algorithm itself is linear, but correctly preserving the structure during both serialization and deserialization requires careful parsing logic.

Serialize and Deserialize N-ary Tree Python/Java solution

Implement a codec class with two methods: serialize(root) and deserialize(data). In Python or Java, perform DFS preorder traversal and append "value, childCount" tokens to a list. During deserialization, parse the tokens and recursively rebuild each node's children. The overall complexity remains O(n) time and O(n) space.

How to solve Serialize and Deserialize N-ary Tree in O(n)?

Traverse the tree once using DFS preorder. Append each node's value followed by its number of children to the serialized list. During deserialization, read tokens sequentially, create a node, and recursively build the next childCount children. Because each node is processed exactly once, the runtime remains O(n).

What is the best approach for Serialize and Deserialize N-ary Tree?

The most common solution uses DFS preorder traversal while storing the number of children for each node. During serialization you record "value, childCount" for every node. During deserialization you recursively rebuild the next childCount nodes. This approach runs in O(n) time and produces a compact representation of the tree.

Is Serialize and Deserialize N-ary Tree asked at Google/Amazon/Meta?

Tree serialization problems are commonly asked at companies like Google, Amazon, and Meta because they test tree traversal, recursion, and data representation skills. Variants include binary tree serialization, N-ary tree encoding, and designing custom data formats for structured data.

What data structure is used in Serialize and Deserialize N-ary Tree?

The core structure is an N-ary tree where each node stores a list of children. Solutions typically use recursion with DFS or a queue for BFS traversal. The serialized representation is usually stored as a string or list of tokens containing node values and child counts.

What is the time complexity of Serialize and Deserialize N-ary Tree?

Both serialization and deserialization run in O(n) time where n is the number of nodes in the tree. Each node is visited exactly once when generating the string and once again when reconstructing the tree. The serialized output and auxiliary data structures also require O(n) space.

Comments

Now write it yourselfClose this page and solve Serialize and Deserialize N-ary Tree in the editor, without looking.
Practise Serialize and Deserialize N-ary Tree