Description
Design an algorithm and write code to serialize and deserialize a binary tree. Writing the tree to a file is called ‘serialization’ and reading back from the file to reconstruct the exact same binary tree is ‘deserialization’.
There is no limit on how to serialize or deserialize a binary tree,you just need to ensure the binary tree can be serialized to a string,and the string can be deserialized to original binary tree.
There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won’t check the result of serialize.
Example
Example 1:
Input:
tree = {3,9,20,#,#,15,7}
Output:
{3,9,20,#,#,15,7}
Explanation:
Binary tree {3,9,20,#,#,15,7}, denote the following structure:
3
/ \
9 20
/ \
15 7
it will be serialized {3,9,20,#,#,15,7}
Example 2:
Input:
tree = {1,2,3}
Output:
{1,2,3}
Explanation:
Binary tree {1,2,3}, denote the following structure:
1
/ \
2 3
it will be serialized {1,2,3}
这题感觉比较难,却又是最常考的题目。以后需要仔细回顾。有两种解法:1)BFS 2)前逆遍历递归
解法1:BFS。参考了网上的一些解法。
代码如下:
/**
* 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 "{}";
string str="{";
queue<TreeNode *> q;
q.push(root);
while(!q.empty()) {
TreeNode* tempNode=q.front();
q.pop();
if (tempNode) {
str+=to_string(tempNode->val);
str+=",";
if (tempNode->left) {
q.push(tempNode->left);
}
else {
q.push(NULL);
}
if (tempNode->right) {
q.push(tempNode->right);
}
else {
q.push(NULL);
}
} else {
str+="#,";
}
}
str+="}";
return str;
}
/**
* 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=="{}") {
return NULL;
}
vector<string> vals=split(data.substr(1, data.size()-2), ",");
TreeNode* root = new TreeNode(stoi(vals[0]));
queue<TreeNode *> q;
q.push(root);
for (int i=1; i<vals.size(); ++i) {
TreeNode* node=q.front();
q.pop();
if (vals[i]!="#") {
node->left=new TreeNode(stoi(vals[i]));
q.push(node->left);
}
i++;
if (vals[i]!="#") {
node->right=new TreeNode(stoi(vals[i]));
q.push(node->right);
}
}
return root;
}
private:
vector<string> split(const string &str, string delim) {
vector<string> results;
int lastIndex = 0, index;
while ((index = str.find(delim, lastIndex)) != string::npos) {
results.push_back(str.substr(lastIndex, index - lastIndex));
lastIndex = index + delim.length();
}
if (lastIndex != str.length()) {
results.push_back(str.substr(lastIndex, str.length() - lastIndex));
}
return results;
}
};
注意:
1) Serialize的时候是相当于标准的BFS分层遍历,需要加while(!q.empty())。Deserialize的时候用的for循环遍历vals数组。这里为什么不用while(!q.empty())还没想通。欢迎留言指教。
解法2:
/**
* 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) {
string res;
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;
}
if (frontNode->left) {
q.push(frontNode->left);
} else {
q.push(NULL);
}
if (frontNode->right) {
q.push(frontNode->right);
} else {
q.push(NULL);
}
}
return res;
}
/**
* 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) {
int len = data.size();
stringstream ss(data);
string token;
vector<string> tokens;
while (ss >> token) tokens.push_back(token);
queue<TreeNode *> q;
int pos = 0;
if (tokens[pos] == "#") return NULL;
TreeNode *root = new TreeNode(stoi(tokens[pos++]));
q.push(root);
while (!q.empty()) {
TreeNode *frontNode = q.front();
q.pop();
if (frontNode && pos < len) {
if (tokens[pos] != "#") {
frontNode->left = new TreeNode(stoi(tokens[pos]));
q.push(frontNode->left);
} else {
q.push(NULL);
}
pos++;
}
if (frontNode && pos < len) {
if (tokens[pos] != "#") {
frontNode->right = new TreeNode(stoi(tokens[pos]));
q.push(frontNode->right);
} else {
q.push(NULL);
}
pos++;
}
}
return root;
}
};