文章目录
- 题目
- 思路
- 问题一
- 问题二
- 代码实现
题目
请实现两个函数,分别用来序列化和反序列化二叉树。
设计一个算法来实现二叉树的序列化与反序列化。不限定序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
以上图为例:
输入: root = [1,2,3,null,null,4,5]
输出:[1,2,3,null,null,4,5]
思路
两个问题:
- 序列化是以怎样的顺序?
- 反序列化是如何进行的?
其实这两个问题也就是让人刚读完题感到无从下手的原因。首先解决第一个问题:
问题一
遍历树无非四种方式——前序、中序、后序、层序。
非常容易得出,本题是按照层序遍历进行的。那么序列化的难点在哪?在于细节实现。
题中描述:不限定序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
说人话就是 空指针不一定要用null表示
,示例中的 []
和 ,
你也可以用别的符号表示,甚至可以不用任何符号(当然逗号尽量不要省去,可以换成别的符号比如空格,主要是必须要有符号来分割节点,否则无法辨别一串字符到底代表几个节点)。
我的选择是用 ~
表示 空指针
,[]
和 ,
保留不变。
要注意几个细节:
- root为空指针时直接返回
[]
。 - 用来保存序列化内容的字符串最好在初始化的时候就加上
[
,在BFS过程中添加的话费时费力。 - 通过BFS实现层序遍历。
- 将
节点
加入字符串
时顺便把,
也加进去。 - 如果
节点为空指针
,则向字符串中加入~,
。 - 记得删除最后一个
,
。 - BFS结束后记得添加
]
。
问题二
以示例中为例,得到的序列化(设为nodes)应为:
[1,2,3, ~ , ~ ,4,5,~ , ~ , ~ , ~]
观察可知,规律为:
- 初始化两个变量
j=0
和pos=1
(0和1指的是节点下标)。 - 有这样的关系
nodes[j]->left=nodes[pos++];
nodes[j]->right=nodes[pos++];
(顺序不能改变)。
需要注意的细节:
- 首先要剥离序列化中的
[
。 - 遍历序列化字符串,遇到
,
之前的为一个节点(每个节点用逗号分隔)。 - 最后一个节点用
]
分割。
代码实现
/*** 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("[");queue<TreeNode*> que;que.push(root);while(!que.empty()){TreeNode* node = que.front();que.pop();if(node){res.append(to_string(node->val) + ",");que.push(node->left);que.push(node->right);}else res.append("~,");}res.erase(res.size()-1);res.append("]");//cout << res << endl;return res;}// Decodes your encoded data to tree.TreeNode* deserialize(string data) {if(data=="[]") return nullptr;vector<TreeNode*> nodes;int i = 1;//剥离'['while(i < data.size()){string stmp = "";while(data[i]!=',' && data[i]!=']'){stmp += data[i];i++;}if(stmp == "~"){nodes.push_back(nullptr);}else{int temp = stoi(stmp);TreeNode* node = new TreeNode(temp);//string转intnodes.push_back(node);}i++;}int pos = 1;//数组构成二叉树映射关系for(int j = 0; j < nodes.size(); j++){if(!nodes[j]) continue;nodes[j]->left = nodes[pos++];nodes[j]->right = nodes[pos++];}return nodes[0];}
};// Your Codec object will be instantiated and called as such:
// Codec codec;
// codec.deserialize(codec.serialize(root));