297. 二叉树的序列化与反序列化+449. 序列化和反序列化二叉搜索树
297. 二叉树的序列化与反序列化
Q:
A:
可以层次遍历、前序、中序。
层次遍历,空节点存个特殊符号标记一下就好,重建树也是按层次BFS重建树。
1 class Codec { 2 public: 3 4 // Encodes a tree to a single string. 5 string serialize(TreeNode* root) 6 { 7 string res(""); 8 queue<TreeNode*> my_queue; 9 my_queue.push(root); 10 vector<string> vec; 11 while(!my_queue.empty()) 12 { 13 TreeNode *cur=my_queue.front(); 14 my_queue.pop(); 15 if(cur==nullptr) 16 { 17 vec.push_back("null"); 18 } 19 else 20 { 21 vec.push_back(to_string(cur->val)); 22 my_queue.push(cur->left); 23 my_queue.push(cur->right); 24 } 25 } 26 while(!vec.empty() and vec.back()=="null") 27 { 28 vec.erase(vec.end()-1); 29 } 30 for (auto s:vec) 31 { 32 res+=s; 33 res+=","; 34 } 35 return res; 36 } 37 38 // Decodes your encoded data to tree. 39 TreeNode* deserialize(string data) 40 { 41 if(data.empty()) 42 { 43 return nullptr; 44 } 45 queue<TreeNode *> my_queue; 46 int le=0,ri=data.find(',',le); //le是节点信息开始位置,ri是紧接着的逗号位置 47 if(ri==-1) 48 { 49 return nullptr; 50 } 51 TreeNode *root=new TreeNode(stoi(data.substr(le,ri-le))); 52 my_queue.push(root); 53 le=ri+1; 54 ri=data.find(',',le); 55 while (ri!=-1) 56 { 57 TreeNode *cur_node=my_queue.front(); 58 my_queue.pop(); 59 //左孩子 60 string p=data.substr(le,ri-le); 61 if(p!="null") 62 { 63 TreeNode *left=new TreeNode(stoi(p)); 64 cur_node->left=left; 65 my_queue.push(left); 66 } 67 //右孩子 68 le=ri+1; 69 ri=data.find(',',le); 70 if(ri==-1) 71 { 72 break; 73 } 74 p=data.substr(le,ri-le); 75 if(p!="null") 76 { 77 TreeNode* right=new TreeNode(stoi(p)); 78 cur_node->right=right; 79 my_queue.push(right); 80 } 81 le=ri+1; 82 ri=data.find(',',le); 83 } 84 return root; 85 } 86 };
中序遍历递归:
1 class Codec { 2 public: 3 4 // Encodes a tree to a single string. 5 string serialize(TreeNode* root) { 6 if(root==nullptr){ 7 return "# "; 8 } 9 string str=to_string(root->val)+" "; 10 str+=serialize(root->left); 11 str+=serialize(root->right); 12 return str; 13 } 14 15 // Decodes your encoded data to tree. 16 TreeNode* deserialize(string data) { 17 // cout<<data; 18 int pos=0; 19 return func(data,pos); 20 } 21 TreeNode* func(const string& data,int& pos){ 22 if(data[pos]=='#'){ 23 pos+=2; 24 return nullptr; 25 } 26 int p=data.find(' ',pos); 27 int num=stoi(data.substr(pos,p-pos)); 28 pos=p+1; 29 TreeNode* cur=new TreeNode(num); 30 cur->left=func(data,pos); 31 cur->right=func(data,pos); 32 return cur; 33 } 34 };
中序遍历用栈,比递归快一点:
中序遍历用栈,比递归快一点:
1 class Codec { 2 public: 3 4 // Encodes a tree to a single string. 5 string serialize(TreeNode* root) { 6 string str=""; 7 decltype(root) cur=root; 8 stack<TreeNode*> sta; 9 while(cur or not sta.empty()){ 10 if(cur){ 11 str+=to_string(cur->val)+" "; 12 sta.push(cur); 13 cur=cur->left; 14 } 15 else{ 16 str+="# "; 17 cur=sta.top()->right; 18 sta.pop(); 19 } 20 } 21 str+="# "; 22 return str; 23 } 24 25 // Decodes your encoded data to tree. 26 TreeNode* deserialize(string data) { 27 // cout<<data; 28 int pos=0; 29 return func(data,pos); 30 } 31 TreeNode* func(const string& data,int& pos){ 32 if(data[pos]=='#'){ 33 pos+=2; 34 return nullptr; 35 } 36 int p=data.find(' ',pos); 37 int num=stoi(data.substr(pos,p-pos)); 38 pos=p+1; 39 TreeNode* cur=new TreeNode(num); 40 cur->left=func(data,pos); 41 cur->right=func(data,pos); 42 return cur; 43 } 44 };
449. 序列化和反序列化二叉搜索树
Q:
A:
这题首先可以用297的代码去套,速度也差不多,但是没有利用二叉搜索树的性质,下面是一个利用搜索树性质的方法。
正常二叉树如果序列化为字符串,想再转化为原二叉树的话,除了按层次建树,需要中序、前序、后序中的至少两个,从而重建二叉树。但对于二叉搜索树,它的中序遍历序列是单调递增的,那么我们可以求出前序或者后序序列任意一个,对其排序就得到了中序序列。这样我们只需要一个前序or后序序列就可以完成二叉搜索树的重建。
/**
* 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;
stack<TreeNode*> sta;
TreeNode *p=root;
while(p or !sta.empty()){ //先序遍历
if(p){
res+=to_string(p->val);
res+="#";
sta.push(p);
p=p->left;
}
else{
p=sta.top()->right;
sta.pop();
}
}
return res;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
vector<int> preorder,midorder;
int i=0,j;
while(i<data.size()){
j=data.find('#',i);
preorder.push_back(stoi(data.substr(i,j-i)));
i=j+1;
}
midorder=preorder;
sort(midorder.begin(),midorder.end());
return helper(preorder,0,preorder.size()-1,midorder,0,midorder.size()-1);
}
TreeNode* helper(vector<int>& pre,int le_pre,int ri_pre,vector<int>& mid,int le_mid,int ri_mid){
if(le_pre>ri_pre or ri_pre>=pre.size() or ri_mid>=mid.size()){
return 0;
}
TreeNode* root=new TreeNode(pre[le_pre]);
int p=find(mid.begin()+le_mid,mid.begin()+ri_mid,pre[le_pre])-mid.begin();
//p是中序序列中根节点的下标
root->left=helper(pre,le_pre+1,le_pre+p-le_mid,mid,le_mid,p-1);
root->right=helper(pre,le_pre+1+p-le_mid,ri_pre,mid,p+1,ri_mid);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
进击的小🐴农