Serialization is the process of converting a complex data structure into a format that can be stored or transmitted and later reconstructed perfectly. Think of it like packing a complex 3D puzzle into a flat box - you need a systematic way to flatten it and rebuild it exactly as it was!
Your challenge is to design an algorithm to serialize (convert to string) and deserialize (reconstruct from string) an N-ary tree, where each node can have any number of children (not just 2 like binary trees).
Goal: Create two functions:
serialize(root) → converts tree to string
deserialize(data) → reconstructs tree from string
Example: A tree with root 1, children [3,2,4], and node 3 having children [5,6] could be serialized as "1[3[5,6],2,4]" or "1,null,3,2,4,5,6,null,null,null,null" - the format is entirely up to you!
Key requirement:deserialize(serialize(tree)) === tree ✨
›Output:serialize(root) = "1,3,3,2,5,0,6,0,2,0,4,0"
deserialize("1,3,3,2,5,0,6,0,2,0,4,0") = original tree
💡 Note:The root node 1 has 3 children. Node 3 has 2 children (5,6). Nodes 2,4,5,6 are leaves with 0 children. The preorder traversal captures the structure perfectly.
example_2.py — Single Node Tree
$Input:root = [1]
Tree structure:
1
›Output:serialize(root) = "1,0"
deserialize("1,0") = Node(1) with empty children list
💡 Note:A single node tree serializes to just the value and children count (0). This is the simplest case - one node, no children.
example_3.py — Deep Linear Tree
$Input:root represents:
1
|
2
|
3
|
4
›Output:serialize(root) = "1,1,2,1,3,1,4,0"
deserialize("1,1,2,1,3,1,4,0") = original linear tree
💡 Note:Each non-leaf node has exactly 1 child, creating a linear chain. The serialization shows: 1→1 child→2→1 child→3→1 child→4→0 children.
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
No restriction on serialization format - be creative!
G
Google 35a
Amazon 28f
Facebook 22⊞
Microsoft 18
Apple 12
Serialize and Deserialize N-ary Tree — Solution
The optimal solution uses preorder traversal with children count encoding. During serialization, we visit each node and record its value followed by the number of children. During deserialization, we use the children count to know exactly how many subtrees to recursively build. This elegant approach achieves O(n) time and O(h) space complexity while producing compact serializations.
Common Approaches
✓
Brute Force (Level-by-Level with Positions)
⏱️ Time: O(n²)
Space: O(n²)
This approach stores extensive metadata for each node including its level, position among siblings, and parent information. While it works, it creates very verbose serializations with redundant information.
Preorder with Markers (Optimal)
⏱️ Time: O(n)
Space: O(h)
This optimal approach uses a preorder traversal (root, then children) with special markers to indicate the structure. We mark the end of each node's children list, allowing perfect reconstruction in a single pass.
Brute Force (Level-by-Level with Positions) — Algorithm Steps
For serialize: traverse tree level by level, storing each node's value with its complete position path
Include level number, sibling index, and parent reference for each node
Create a verbose string with all this metadata
For deserialize: parse all the metadata to reconstruct parent-child relationships
Build the tree by processing each level and connecting nodes to their parents
Visualization
Tap to expand
Step-by-Step Walkthrough
1
Level-by-Level Traversal
Visit nodes level by level, storing complete position information
2
Metadata Collection
For each node, collect value, level, parent path, and sibling index
3
Verbose Encoding
Create detailed string with all metadata for later reconstruction
Code -
solution.c — C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
int val;
int numChildren;
struct Node** children;
};
struct Node* createNode(int val) {
struct Node* node = (struct Node*)malloc(sizeof(struct Node));
node->val = val;
node->numChildren = 0;
node->children = NULL;
return node;
}
static char serializeResult[100000];
static int serializePos;
void serializeDFS(struct Node* node) {
if (!node) return;
char temp[50];
// Add comma if not first element
if (serializePos > 0) {
serializeResult[serializePos++] = ',';
}
// Add node value
sprintf(temp, "%d", node->val);
strcpy(serializeResult + serializePos, temp);
serializePos += strlen(temp);
// Add comma and child count
serializeResult[serializePos++] = ',';
sprintf(temp, "%d", node->numChildren);
strcpy(serializeResult + serializePos, temp);
serializePos += strlen(temp);
// Recursively serialize children
for (int i = 0; i < node->numChildren; i++) {
serializeDFS(node->children[i]);
}
}
char* serialize(struct Node* root) {
if (!root) {
char* result = (char*)malloc(1);
result[0] = '\0';
return result;
}
serializeResult[0] = '\0';
serializePos = 0;
serializeDFS(root);
serializeResult[serializePos] = '\0';
char* result = (char*)malloc(serializePos + 1);
strcpy(result, serializeResult);
return result;
}
static char** tokens;
static int tokenCount;
static int deserializeIndex;
struct Node* buildTree() {
if (deserializeIndex >= tokenCount) {
return NULL;
}
int val = atoi(tokens[deserializeIndex++]);
if (deserializeIndex >= tokenCount) {
return createNode(val);
}
int childCount = atoi(tokens[deserializeIndex++]);
struct Node* node = createNode(val);
if (childCount > 0) {
node->children = (struct Node**)malloc(childCount * sizeof(struct Node*));
node->numChildren = childCount;
for (int i = 0; i < childCount; i++) {
struct Node* child = buildTree();
if (child) {
node->children[i] = child;
}
}
}
return node;
}
struct Node* deserialize(char* data) {
if (!data || strlen(data) == 0) {
return NULL;
}
static char dataCopy[100000];
static char* tokenArray[10000];
strcpy(dataCopy, data);
tokens = tokenArray;
tokenCount = 0;
deserializeIndex = 0;
char* token = strtok(dataCopy, ",");
while (token != NULL && tokenCount < 10000) {
tokens[tokenCount++] = token;
token = strtok(NULL, ",");
}
return buildTree();
}
struct Node* buildTreeFromArray(int* arr, int size) {
if (size == 0) return NULL;
struct Node* root = createNode(arr[0]);
if (size == 1) return root;
static struct Node* queue[10000];
int front = 0, rear = 0;
queue[rear++] = root;
int i = 2;
while (front < rear && i < size) {
struct Node* parent = queue[front++];
static struct Node* children[1000];
int childCount = 0;
while (i < size && arr[i] != -1) {
struct Node* child = createNode(arr[i]);
children[childCount] = child;
queue[rear++] = child;
childCount++;
i++;
}
if (childCount > 0) {
parent->children = (struct Node**)malloc(childCount * sizeof(struct Node*));
parent->numChildren = childCount;
for (int k = 0; k < childCount; k++) {
parent->children[k] = children[k];
}
}
i++; // Skip null
}
return root;
}
int treesEqual(struct Node* root1, struct Node* root2) {
if (!root1 && !root2) return 1;
if (!root1 || !root2) return 0;
if (root1->val != root2->val) return 0;
if (root1->numChildren != root2->numChildren) return 0;
for (int i = 0; i < root1->numChildren; i++) {
if (!treesEqual(root1->children[i], root2->children[i])) {
return 0;
}
}
return 1;
}
int main() {
char inputLine[10000];
fgets(inputLine, sizeof(inputLine), stdin);
// Remove newline
inputLine[strcspn(inputLine, "\n")] = 0;
static int arr[10000];
int size = 0;
if (strcmp(inputLine, "[]") != 0) {
// Parse input format like "1,,3,2,4,5,6"
char* p = inputLine;
char* start = p;
while (1) {
if (*p == ',' || *p == '\0') {
// Found a token
if (p == start) {
// Empty token (represents null)
arr[size++] = -1; // Use -1 as null marker
} else {
// Non-empty token, parse as number
char temp = *p;
*p = '\0';
if (strcmp(start, "null") == 0) {
arr[size++] = -1;
} else {
arr[size++] = atoi(start);
}
*p = temp;
}
if (*p == '\0') break;
p++;
start = p;
} else {
p++;
}
}
}
// Build tree
struct Node* root = buildTreeFromArray(arr, size);
// Test serialize/deserialize
char* serialized = serialize(root);
struct Node* deserialized = deserialize(serialized);
// Check if trees are equal
int result = treesEqual(root, deserialized);
printf("%s\n", result ? "true" : "false");
free(serialized);
return 0;
}
Time & Space Complexity
Time Complexity
⏱️
O(n²)
Each node requires processing its full path information, leading to quadratic time in the worst case for deep trees
n
2n
✓ Linear Growth
Space Complexity
O(n²)
Storing complete path information for each node can require quadratic space for deep trees
n
2n
✓ Linear Space
89.3K Views
MediumFrequency
~25 minAvg. Time
1.8K Likes
Ln 1, Col 1
Smart Actions
💡Explanation
AI Ready
💡 SuggestionTabto acceptEscto dismiss
// Output will appear here after running code
Code Editor Closed
Click the red button to reopen
Algorithm Visualization
Pinch to zoom • Tap outside to close
Test Cases
0 passed
0 failed
3 pending
Select Compiler
Choose a programming language
Compiler list would appear here...
AI Editor Features
Header Buttons
💡
Explain
Get a detailed explanation of your code. Select specific code or analyze the entire file. Understand algorithms, logic flow, and complexity.
🔧
Fix
Automatically detect and fix issues in your code. Finds bugs, syntax errors, and common mistakes. Shows you what was fixed.
💡
Suggest
Get improvement suggestions for your code. Best practices, performance tips, and code quality recommendations.
💬
Ask AI
Open an AI chat assistant to ask any coding questions. Have a conversation about your code, get help with debugging, or learn new concepts.
Smart Actions (Slash Commands)
🔧
/fix Enter
Find and fix issues in your code. Detects common problems and applies automatic fixes.
💡
/explain Enter
Get a detailed explanation of what your code does, including time/space complexity analysis.
🧪
/tests Enter
Automatically generate unit tests for your code. Creates comprehensive test cases.
📝
/docs Enter
Generate documentation for your code. Creates docstrings, JSDoc comments, and type hints.
⚡
/optimize Enter
Get performance optimization suggestions. Improve speed and reduce memory usage.
AI Code Completion (Copilot-style)
👻
Ghost Text Suggestions
As you type, AI suggests code completions shown in gray text. Works with keywords like def, for, if, etc.
Tabto acceptEscto dismiss
💬
Comment-to-Code
Write a comment describing what you want, and AI generates the code. Try: # two sum, # binary search, # fibonacci
💡
Pro Tip: Select specific code before using Explain, Fix, or Smart Actions to analyze only that portion. Otherwise, the entire file will be analyzed.