- Serialize and Deserialize BST
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.
Example
Example 1:
Input:[2,1,3]
Output:[2,1,3]
Explanation:
2
/ \
1 3
Example 2:
Input:[1,#,2]
Output:[1,#,2]
Explanation:
1
\
2
解法1:DFS
serialize()用preOrder遍历,如果遇到空节点,就输出”# “,否则就输出val + " "。
deserialize()检查节点为空则输出NULL,否则递归调用deserialize()为当前节点的左节点和右节点。
注意:
1)我们以前学过光靠preOrder或postOrder或inOrder是不能决定一个Binary Tree的,这里为什么可以呢?因为这里serialize()把该Binary Tree变成了满二叉树。对于满二叉树,preOrder/postOrder/inOrder是可以决定这棵树的。
2) stringStream 很有用,自动把string按“ ”split成tokens。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
string serialize(TreeNode * root) {
stringstream ss;
serialize(root, ss);
return ss.str();
}
TreeNode * deserialize(string &data) {
stringstream ss(data);
return deserialize(ss);
}
private:
void serialize(TreeNode * root, stringstream & ss) {
if (!root) ss << "# ";
else {
ss << root->val << " ";
serialize(root->left, ss);
serialize(root->right, ss);
}
}
TreeNode * deserialize(stringstream & ss) {
string val = "";
ss >> val;
if (val == "#") return NULL;
TreeNode * node = new TreeNode(stoi(val));
node->left = deserialize(ss);
node->right = deserialize(ss);
return node;
}
};
另一种写法:会超时。可能是因为vector的erase操作时间复杂度太高。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
if (!root) return "# ";
string res = to_string(root->val) + " ";
res = res + serialize(root->left) + serialize(root->right);
return res;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
stringstream ss(data);
vector<string> tokens;
string token;
while (ss >> token) {
tokens.push_back(token);
}
return deserialize(tokens);
}
private:
TreeNode* deserialize(vector<string> &tokens) {
if (tokens.empty()) return NULL;
string token = tokens[0];
tokens.erase(tokens.begin());
TreeNode *root;
if (token == "#") root = NULL;
else {
root = new TreeNode(stoi(token));
root->left = deserialize(tokens);
root->right = deserialize(tokens);
}
return root;
}
};
改用deque,就可以通过。
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
if (!root) return "# ";
string res = to_string(root->val) + " ";
res = res + serialize(root->left) + serialize(root->right);
return res;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
stringstream ss(data);
deque<string> tokens;
string token;
while (ss >> token) {
tokens.push_back(token);
}
return deserialize(tokens);
}
private:
TreeNode* deserialize(deque<string> &tokens) {
if (tokens.empty()) return NULL;
string token = tokens.front();
tokens.pop_front();
TreeNode *root;
if (token == "#") root = NULL;
else {
root = new TreeNode(stoi(token));
root->left = deserialize(tokens);
root->right = deserialize(tokens);
}
return root;
}
};
解法2:BFS
serialize()和deserialize()都是按层次遍历来处理。
注意:
1) if (!(ss >> val)) 说明ss的token已经处理完了。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
string serialize(TreeNode * root) {
if (!root) return "";
stringstream ss;
queue<TreeNode *> q;
q.push(root);
while(!q.empty()) {
TreeNode * node = q.front();
q.pop();
if (node) {
ss << node->val << " ";
q.push(node->left);
q.push(node->right);
} else {
ss << "# ";
}
}
// cout<<"ss.str()="<<ss.str()<<endl;
return ss.str();
}
TreeNode * deserialize(string &data) {
if (data.empty()) return NULL;
stringstream ss;
ss << data; //stringstream ss(data) is also OK
queue<TreeNode *> q;
string val = "";
ss >> val; // the first token
TreeNode * resNode = new TreeNode(stoi(val));
TreeNode * curNode;
q.push(resNode);
while(!q.empty()) {
TreeNode * node = q.front();
q.pop();
if (!(ss >> val)) break; //ss reads to the end!
if (val != "#") {
curNode = new TreeNode(stoi(val));
q.push(curNode);
node->left = curNode;
}
if (!(ss >> val)) break; //ss reads to the end!
if (val != "#") {
curNode = new TreeNode(stoi(val));
q.push(curNode);
node->right = curNode;
}
}
return resNode;
}
};
代码同步在
https://github.com/luqian2017/Algorithm
二刷:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string res;
if (!root) return "";
queue<TreeNode *> q;
q.push(root);
while (!q.empty()) {
TreeNode *frontNode = q.front();
q.pop();
if (frontNode) {
res += to_string(frontNode->val) + " ";
} else {
res += "# ";
continue;
}
q.push(frontNode->left);
q.push(frontNode->right);
}
return res;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
TreeNode *root;
if (data.size() == 0) return nullptr;
stringstream ss(data);
string token;
vector<string> tokens;
//tokenize
while (ss >> token) {
tokens.push_back(token);
}
//BFS
int pos = 0;
int len = tokens.size();
queue<TreeNode *> q;
root = new TreeNode(stoi(tokens[pos++]));
q.push(root);
while (!q.empty()) {
TreeNode *frontNode = q.front();
q.pop();
if (pos < len) {
token = tokens[pos++];
if (token != "#") {
frontNode->left = new TreeNode(stoi(token));
q.push(frontNode->left);
}
}
if (pos < len) {
token = tokens[pos++];
if (token != "#") {
frontNode->right = new TreeNode(stoi(token));
q.push(frontNode->right);
}
}
}
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec* ser = new Codec();
// Codec* deser = new Codec();
// string tree = ser->serialize(root);
// TreeNode* ans = deser->deserialize(tree);
// return ans;
三刷: 注意采用DFS的方法不同于BFS,这里是基于preorder,以tree = {3,9,20,#,#,15,7},Serialize的结果为 “3 9 # # 20 15 # # 7 # #” 。9下面会有两个"# “,而上面的BFS会生成"3 9 20 # # 15 7 # # # #”。
/**
* Definition of TreeNode:
* class TreeNode {
* public:
* int val;
* TreeNode *left, *right;
* TreeNode(int val) {
* this->val = val;
* this->left = this->right = NULL;
* }
* }
*/
class Solution {
public:
/**
* This method will be invoked first, you should design your own algorithm
* to serialize a binary tree which denote by a root node to a string which
* can be easily deserialized by your own "deserialize" method later.
*/
string serialize(TreeNode * root) {
if (!root) return "# ";
return to_string(root->val) + " " + serialize(root->left) + " " + serialize(root->right);
}
/**
* This method will be invoked second, the argument data is what exactly
* you serialized at method "serialize", that means the data is not given by
* system, it's given by your own serialize method. So the format of data is
* designed by yourself, and deserialize it here as you serialize it in
* "serialize" method.
*/
TreeNode * deserialize(string &data) {
if (data.empty()) return NULL;
TreeNode *root;
stringstream ss(data);
root = helper(ss);
return root;
}
private:
TreeNode * helper(stringstream &ss) {
string token;
TreeNode *root;
if (ss >> token) {
if (token != "#") {
root = new TreeNode(stoi(token));
} else {
return NULL;
}
}
root->left = helper(ss);
root->right = helper(ss);
return root;
}
};