Article Directory
1. Source title
Links: sequence of binary tree
Source: LeetCode-- "prove safety -Offer" special
2. Description title
Implement two functions are used to serialize and deserialize binary tree.
Example:
You can use the following binary tree:
1 / \ 2 3 / \ 4 5
Serialized as "[1,2,3, null, null, 4,5]"
3. resolve title
Method a: Sequence Iterative Method traversal +
This is a Hard
problem, the idea is still very clear, the challenge in a string of data processing and final test on the 47, 48 receiving.
- Sequence using the binary tree traversal sequence. Traverse the level is not uniquely identify a binary tree. If you encounter a node with an empty node
'#'
represents. Add a back of each node','
represents the end, you can uniquely identify a binary tree. - Above to give the binary tree of hierarchical sequence
1,2,3,#,#,4,5,#,#,#,#,
- Then deserialized based on this sequence. (Note that the case of a negative judgment)
I talk about the pit encountered it:
- First, in the sequence of the time, can not be directly used
string
in thepush_back
method, it is hard on the test case 47, 48 may take+=
the form of a string, it may be used character stream in the form of - Not merely use a sequence of hierarchically manner, i.e. not only added
#
to split the string, to do so one could not uniquely determine the binary tree, when the tree node valueval
greater than 10, there is no way to directly remove the normalval
value, since the#12#
ambiguity, I do not know in the end is1、2
still12
- The situation is negative nodes need to be addressed, this is indeed the beginning to ignore the
- Rearmost
#
need to be removed, this is very easy to think
Basically a large pit in the above points are prompted to, it really Hard
is not a simple general ... dfs、bfs
I just put my whole temper ...
Bad Solution 1
Thinking too young to write so cool, I had not ... here is shaping val
into a char
type, so string
take the case to bit can be taken directly.
See the code below:
// 没 AC,样例 47/48 过不去
// [1,null,2,null,3,null,4,null,5,null,6,null,...,999,null,1000] 单支树,IO极其密集
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s;
queue<TreeNode*> q;
if (root) q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (t) {
s.push_back(t->val); // 过不去,string 爆掉了
q.push(t->left);
q.push(t->right);
} else {
s.push_back('#');
}
}
return s;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int cnt = data.find_last_not_of('#');
if (cnt != std::string::npos)
data.erase(cnt + 1);
else
data.clear();
if (data.empty()) return nullptr;
queue<TreeNode*> q;
string val(data);
TreeNode *res = new TreeNode(val[0]), *cur = res;
q.push(cur);
int i = 1;
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (i > val.size() - 1) break;
if (val[i] != '#') {
cur = new TreeNode(val[i]);
q.push(cur);
t->left = cur;
++i;
}
else {
++i;
}
if (i > val.size() - 1) break;
if (val[i] != '#') {
cur = new TreeNode(val[i]);
q.push(cur);
t->right = cur;
++i;
}
else {
++i;
}
}
return res;
}
};
2 bad solution
Operating flow into the string can be properly read the test case 47, so read by character, integer will 123
split into 1
2
3
, three characters, in a subsequent string [ ]
operation can not complete the output integer, it is being given. Even if the string processing, but only add the string #
to the string dividing, no way to uniquely identify a binary tree, when the tree node value val
greater than 10, there is no way to directly remove the normal val
value, since the #12#
ambiguity, no know in the end is 1、2
still 12
, so to be considered uniquely identify a binary tree!
class Codec {
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
queue<TreeNode*> q;
q.push(root);
stringstream ss;
while (!q.empty()) {
root = q.front();
q.pop();
if (root) {
q.push(root->left);
q.push(root->right);
ss << root->val;
}
else {
ss << '#';
}
}
string data = ss.str();
return data;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int cnt = data.find_last_not_of('#');
if (cnt != std::string::npos)
data.erase(cnt + 1);
else
data.clear();
if (data.empty()) return nullptr;
queue<TreeNode*> q;
string val(data);
TreeNode *res = new TreeNode(val[0] -'0'), *cur = res;
q.push(cur);
int i = 1;
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (i > val.size() - 1) break;
if (val[i] != '#' && i < val.size() - 1) {
string tmp;
while (i < val.size() && val[i] != '#' ) {
tmp += val[i];
++i;
}
cur = new TreeNode(stoi(tmp));
q.push(cur);
t->left = cur;
}
else {
++i;
}
if (i > val.size() - 1) break;
if (val[i] != '#') {
string tmp;
while (i < val.size() && val[i] != '#') {
tmp += val[i];
++i;
}
cur = new TreeNode(stoi(tmp));
q.push(cur);
t->right = cur;
}
else {
++i;
}
}
return res;
}
};
Success edition
To get rid of these problems, and then solve the problem of negative numbers, to get this problem!
See the code below:
// 执行用时 :8 ms, 在所有 C++ 提交中击败了84.14%的用户
// 内存消耗 :10 MB, 在所有 C++ 提交中击败了100.00%的用户
/**
* 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 {
private:
string encode(TreeNode* root) {
if (!root) return "#,";
string res = "";
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
if (t) {
res += to_string(t->val) + ",";
q.push(t->left);
q.push(t->right);
} else {
res += "#,";
}
}
return res;
}
TreeNode* takeNum(const string& data, int& p) {
if (data[p] == '#') {
p += 2;
return NULL;
}
bool isN = false;
if (data[p] == '-') {
isN = true;
p++;
}
int val = 0;
while (data[p] != ',') {
val = val * 10 + (data[p] - '0');
p++;
}
p++;
if (isN) {
val = -val;
}
return new TreeNode(val);
}
TreeNode* decode(const string& data) {
if (data[0] == '#') return NULL;
int p = 0;
TreeNode *root = takeNum(data, p);
queue<TreeNode*> q;
q.push(root);
while (!q.empty()) {
TreeNode *t = q.front(); q.pop();
TreeNode *l = takeNum(data, p);
TreeNode *r = takeNum(data, p);
if (l) q.push(l);
if (r) q.push(r);
t->left = l;
t->right = r;
}
return root;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string s = encode(root);
return s;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
TreeNode *root = decode(data);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
Method two: preorder recursive solution +
String via the input and output streams istringstream
and ostringstream
.
- For serialization, starting from the root, if the node exists, then the current value stored in the output string, and each function can be serialized to its left and right child nodes recursively.
- Go for serialization, first read the first character, in order to generate a root node, and then call to serialize function to the left and right child nodes of the root node recursively
- Or deal with details of the problem, and almost above, will not repeat, but obviously a lot of simple recursive
See the code below:
// 执行用时 :40 ms, 在所有 C++ 提交中击败了63.53%的用户
// 内存消耗 :26.5 MB, 在所有 C++ 提交中击败了100.00%的用户
/**
* 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) {
ostringstream out;
serialize(root, out);
return out.str();
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
istringstream in(data);
return deserialize(in);
}
private:
void serialize(TreeNode *root, ostringstream &out) {
if (root) {
out << root->val << ' ';
serialize(root->left, out);
serialize(root->right, out);
} else {
out << "# ";
}
}
TreeNode* deserialize(istringstream &in) {
string val;
in >> val;
if (val == "#") return nullptr;
TreeNode *root = new TreeNode(stoi(val));
root->left = deserialize(in);
root->right = deserialize(in);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));