Description
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 search tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary search tree can be serialized to a string and this string can be deserialized to the original tree structure.
The encoded string should be as compact as possible.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
Solution
将一棵二叉搜索树序列化,并能重构回来。
First, we add two constant, SEP is used for seperate each nodes, NULL denotes “null” value.
In serialize, we use pre-order traversal which could construct a string with small nodes all ahead of root and big nodes all after root. Using a stack to perform this operation, append root first, then right first, left last. It is different from recursive approach, because stack is LIFO, so we have to push left last.
In deserialize, judge the data string is null or not. Then using a queue to store the nodes after split by SEP. Recursively get the tree. Get root first, then get the nodes whos value is smaller than root.val, offer them to a new queue. Then recursively get root’s left and right.
Code
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
private static final String SEP = ",";
private static final String NULL = "X";
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null){
return NULL;
}
StringBuilder sb = new StringBuilder();
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
//add treeNode to sb in pre-order iteratively
while(!stack.empty()){
root = stack.pop();
sb.append(root.val).append(SEP);
if (root.right != null){
stack.push(root.right);
}
if (root.left != null){
stack.push(root.left);
}
}
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data.equals(NULL)){
return null;
}
//split by SEP and store int value into queue to get tree.
String[] strs = data.split(SEP);
Queue<Integer> queue = new LinkedList<>();
for (String s : strs){
queue.offer(Integer.parseInt(s));
}
return getTree(queue);
}
private TreeNode getTree(Queue<Integer> queue){
if (queue.isEmpty()){
return null;
}
TreeNode root = new TreeNode(queue.poll());
//get the value smaller than root.val to a new queue to get root.left recursively.
Queue<Integer> left = new LinkedList<>();
while (!queue.isEmpty() && queue.peek() < root.val){
left.offer(queue.poll());
}
root.left = getTree(left);
root.right = getTree(queue);
return root;
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
Time Complexity: O(n)
Space Complexity: O(n)