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.
For example, you may serialize the following tree
1
/ \
2 3
/ \
4 5
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ 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.
Update on 1/28/16:
BFS by removing the trailing "null" node strings.
One advantage of using BFS is we could safely removing the trailing last-level null nodes represented by the "#," string. This can save about half space (The # nodes in last-level of a binary tree is around half of the total number of trees).
Code (Java):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "";
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
StringBuffer sb = new StringBuffer();
while (!queue.isEmpty()) {
TreeNode curr = queue.poll();
if (curr != null) {
sb.append(curr.val + ",");
queue.offer(curr.left);
queue.offer(curr.right);
} else {
sb.append("#" + ",");
}
}
// Remove the trailing #
String result = sb.toString();
int j = result.length() - 1;
while (j > 0 && result.charAt(j) == ',' && result.charAt(j) == '#') {
j -= 2;
}
result = result.substring(0, j);
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
Queue<TreeNode> queue = new LinkedList<>();
String[] nodes = data.split(",");
TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
queue.offer(root);
int i = 1;
while (!queue.isEmpty() && i < nodes.length) {
TreeNode curr = queue.poll();
if (nodes[i].equals("#")) {
curr.left = null;
} else {
TreeNode leftNode = new TreeNode(Integer.parseInt(nodes[i]));
curr.left = leftNode;
queue.offer(leftNode);
}
i++;
if (i >= nodes.length) {
break;
}
// right node
if (nodes[i].equals("#")) {
curr.right = null;
} else {
TreeNode rightNode = new TreeNode(Integer.parseInt(nodes[i]));
curr.right = rightNode;
queue.offer(rightNode);
}
i++;
}
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
DFS solution with using a Deque:
We can also solve the problem by using pre-order traversal of the binary tree. We need to use a deque because each time we need to remove one element from the top. Else we need to maintain a global index pointing to the current element we want to add into the tree.
Code (Java):
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "";
}
StringBuffer sb = new StringBuffer();
serializeHelper(root, sb);
return sb.toString();
}
private void serializeHelper(TreeNode root, StringBuffer sb) {
if (root == null) {
sb.append("#");
sb.append(",");
return;
}
sb.append(root.val + ",");
serializeHelper(root.left, sb);
serializeHelper(root.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
String[] strs = data.split(",");
Deque<String> deque = new LinkedList<>(Arrays.asList(strs));
return deserializeHelper(deque);
}
private TreeNode deserializeHelper(Deque<String> deque) {
if (deque.isEmpty()) {
return null;
}
String node = deque.removeFirst();
if (node.equals("#")) {
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(node));
root.left = deserializeHelper(deque);
root.right = deserializeHelper(deque);
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
Another DFS without using a Deque, but a global index.
public class Solution2 {
public String serialdfs(TreeNode root) {
if (root == null) {
return "";
}
StringBuilder sb = new StringBuilder();
serialdfsHelper(root, sb);
return sb.toString();
}
private void serialdfsHelper(TreeNode root, StringBuilder sb) {
if (root == null) {
sb.append("#");
return;
}
sb.append(root.val);
serialdfsHelper(root.left, sb);
serialdfsHelper(root.right, sb);
}
public int i = 0;
public TreeNode deserialdfs(String s) {
if (s == null || s.length() == 0) {
return null;
}
return deserialdfsHelper(s);
}
private TreeNode deserialdfsHelper(String s) {
if (i >= s.length() || s.charAt(i) == '#') {
return null;
}
TreeNode root = new TreeNode(s.charAt(i) - '0');
i++;
root.left = deserialdfsHelper(s);
i++;
root.right = deserialdfsHelper(s);
return root;
}
public static void main(String[] args) {
Solution2 sol = new Solution2();
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(5);
String result = sol.serialdfs(root);
TreeNode root2 = sol.deserialdfs(result);
String result2 = sol.serialdfs(root2);
System.out.println(result2);
}
}
Compare between DFS and BFS:
I would like more BFS because BFS sometimes can save more space. For example,
1
/ \
2 3
/ \ / \
4 # # #
/ \
# #
By BFS: the serialized tree is 1,2,3,4
By DFS, the serialized tree is 1,2,4,#,#,#,3, which needs more space to store.
No comments:
Post a Comment