Reference: LeetCode
Difficulty: Hard

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]]. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

Note:

  • N is in the range of [1, 1000].
  • Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

Example:

1
2
3
4
5
6
7
You may serialize the following tree:
1
/ \
2 3
/ \
4 5
as "[1,2,3,null,null,4,5]"

Clarification: The above 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.

Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.

Analysis

BFS

Note:

Time: $O(N)$ if using StringBuffer for string concatenation.
Space: $O(N)$ since we need to keep the entire tree.

Serialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public String serialize(Node root) {
if (root == null) {
return null;
}
StringBuffer sb = new StringBuffer();
serializeHelper(root, sb);
sb.setLength(sb.length() - 1);
return sb.toString();
}


private void serializeHelper(Node root, StringBuffer sb) {
if (root == null) {
return;
}
Queue<Node> queue = new LinkedList<>();
queue.offer(root);

while (queue.size() > 0) {
int childSize = queue.size();
for (int i = 0; i < childSize; ++i) {
Node p = queue.poll(); // assume not null
sb.append(p.val + ",");
sb.append(p.children.size() + ",");
for (Node child : p.children) {
queue.offer(child);
}
}
}
}

Deserialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public Node deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}

String[] dataArray = data.split(",");
List<String> dataList = new ArrayList<>(Arrays.asList(dataArray));

int index = 0;
Queue<Node> queue = new LinkedList<>();
Queue<Integer> sizeQueue = new LinkedList<>();
Node root = new Node(Integer.valueOf(dataList.get(index)));
queue.offer(root);
index += 1;
sizeQueue.offer(Integer.valueOf(dataList.get(index)));
index += 1;

while (queue.size() > 0) {
int childSize = queue.size();
for (int i = 0; i < childSize; ++i) {
Node curr = queue.poll(); // not null
int currChildSize = sizeQueue.poll();
curr.children = new ArrayList<>(currChildSize);
for (int j = 0; j < currChildSize; ++j) {
int nodeVal = Integer.valueOf(dataList.get(index));
index += 1;
int nodeSize = Integer.valueOf(dataList.get(index));
index += 1;
Node child = new Node(nodeVal);
curr.children.add(child);
queue.offer(child);
sizeQueue.offer(nodeSize);
}
}
}

return root;

}

DFS (Solution)

Time: $O(N)$ if using StringBuffer for string concatenation.
Space: $O(N)$ since we need to keep the entire tree.

Serialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public String serialize(Node root) {
if (root == null) {
return null;
}
StringBuffer sb = new StringBuffer();
rserialize(root, sb);

return sb.toString();
}


private void rserialize(Node root, StringBuffer sb) {
// No base case is required
sb.append(root.val + ",");
sb.append(root.children.size() + ","); // record the size of children

for (Node node : root.children) { // when children.size() == 0, it will return
rserialize(node, sb);
}
}

Deserialize:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public Node deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] dataArray = data.split(",");
List<String> dataList = new LinkedList<>(Arrays.asList(dataArray));
return rdeserialize(dataList);
}

private Node rdeserialize(List<String> L) {
if (L == null || L.size() == 0) {
return null;
}
Node root = new Node(Integer.valueOf(L.get(0)));
L.remove(0);
int childSize = Integer.valueOf(L.get(0));
L.remove(0);
root.children = new ArrayList<>();
for (int i = 0; i < childSize; ++i) {
root.children.add(rdeserialize(L));
}
return root;
}