297. 二叉树的序列化与反序列化
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5
序列化为 “[1,2,3,null,null,4,5]”
提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。
解题
若按生成给定的string,难以反序列化,所以需要自定义中间的序列化结果;
BFS建序列+dfs建树(超时-测试点48)
队列操作太慢,超时;
/**
* 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:
void Dfs(TreeNode *root,int cur,int &cnt){
if(!root){
cnt=max(cur,cnt);
return;
}
Dfs(root->left,cur+1,cnt);
Dfs(root->right,cur+1,cnt);
return;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
int cnt=0; //记录层数
//若到最后一层则无需记录
Dfs(root,0,cnt);
//得到层数cnt
vector<TreeNode*> res;
queue<TreeNode*> Q;
Q.push(root);
int curcnt=1;//当前层数
while(!Q.empty()){
if(curcnt>cnt) break;
int size=Q.size();
for(int i=0;i<size;i++){
TreeNode *tmp=Q.front();
Q.pop();
if(curcnt<=cnt) res.push_back(tmp);
if(tmp){
Q.push(tmp->left);
Q.push(tmp->right);
}else {
Q.push(NULL);
Q.push(NULL);
}
}
curcnt++;
}
string result="[";
for(auto t:res){
if(t) result+=to_string(t->val)+",";
else result+="null,";
}
result.pop_back();
result+="]";
//cout<<result;
return result;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
if(data[1]=='n') return NULL;
//空树
vector<string> node; //把data里的数存入node中
int i=1;
int start=1;
while(i<data.size()){
if(data[start]=='n'){
i+=4;
}
else{
while(i<data.size()&&(isdigit(data[i])||data[i]=='-')) i++;
}
node.push_back(data.substr(start,i-start));
i++;
start=i;
}
TreeNode *root=dfs(node,0);
return root;
}
private:
//第1层 0 左子树1*2-1=1 右子树 1*2+1-1=2
TreeNode* dfs(vector<string> &node,int curfloor){
if(curfloor>=node.size()) return NULL;
if(node[curfloor]=="null") return NULL;
TreeNode *root=new TreeNode(stoi(node[curfloor]));
root->left=dfs(node,curfloor*2+1);
root->right=dfs(node,curfloor*2+2);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
dfs建前序序列+dfs建树(超时-测试点45)
substr操作太慢,超时;
/**
* 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:
void dfs(TreeNode *root,vector<string>& node){
if(!root) {
node.push_back("null");
return;
}
node.push_back(to_string(root->val));
dfs(root->left,node);
dfs(root->right,node);
return;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
vector<string> res;
dfs(root,res);
string S="[";
for(auto t:res)
S+=t+",";
S.pop_back();
S+="]";
//cout<<S;
return S;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
data=data.substr(1);
return dfs(data);
}
private:
TreeNode* dfs(string &data){
if(!data.size()) return NULL;
if(data[0]=='n') {
data=data.substr(5); //跳过逗号
return NULL;
}
int num=0;
int flag=1;
int i=0;
if(data[i]=='-') {flag=-1;i++;}
while(i<data.size()&&isdigit(data[i])) num=num*10+data[i++]-'0';
num*=flag;
TreeNode *root=new TreeNode(num);
//此时i指向逗号
data=data.substr(i+1); //i指向逗号,或】
root->left=dfs(data);
root->right=dfs(data);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
将上述代码的substr改为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 {
private:
void dfs(TreeNode *root,vector<string>& node){
if(!root) {
node.push_back("null");
return;
}
node.push_back(to_string(root->val));
dfs(root->left,node);
dfs(root->right,node);
return;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
vector<string> res;
dfs(root,res);
string S="";
for(auto t:res)
S+=t+",";
//S.pop_back();
//cout<<S;
return S;
}
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
return dfs(data);
}
private:
TreeNode* dfs(string &data){
if(!data.size()) return NULL;
if(data[0]=='n') {
data.erase(0,5); //跳过逗号
return NULL;
}
int num=0;
int flag=1;
int i=0;
if(data[i]=='-') {flag=-1;i++;}
while(i<data.size()&&isdigit(data[i])) num=num*10+data[i++]-'0';
num*=flag;
TreeNode *root=new TreeNode(num);
//此时i指向逗号
data.erase(0,i+1); //i指向逗号,或】
root->left=dfs(data);
root->right=dfs(data);
return root;
}
};
// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));
序列化操作优化——将中间的string序列简化,不经过vector,直接生成
private:
void dfs(TreeNode *root,string &res){
if(!root) {
res+="n,";
return;
}
res+=to_string(root->val)+",";
dfs(root->left,res);
dfs(root->right,res);
return;
}
public:
// Encodes a tree to a single string.
string serialize(TreeNode* root) {
string res="";
dfs(root,res);
//cout<<res;
return res;
}
反序列化操作优化——不用erase,用下标的引用来生成二叉树;
// Decodes your encoded data to tree.
TreeNode* deserialize(string data) {
int i=0;
return dfs(data,i);
}
private:
TreeNode* dfs(string &data,int &i){
if(i>=data.size()) return NULL;
if(data[i]=='n') {
i+=2;
return NULL;
}
int num=0;
int flag=1;
if(data[i]=='-') {flag=-1;i++;}
while(i<data.size()&&isdigit(data[i])) num=num*10+data[i++]-'0';
num*=flag;
TreeNode *root=new TreeNode(num);
//此时i指向逗号
i++; //跳过逗号
root->left=dfs(data,i);
root->right=dfs(data,i);
return root;
}