题干
序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。
请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。
示例:
你可以将以下二叉树
1
/ \
2 3
/ \
4 5
序列化为 “[1,2,3,null,null,4,5]”
提示: 这与 LeetCode 目前使用的方式一致,详情请参阅 LeetCode 序列化二叉树的格式。你并非必须采取这种方式,你也可以采用其他的方法解决这个问题。
说明: 不要使用类的成员 / 全局 / 静态变量来存储状态,你的序列化和反序列化算法应该是无状态的。
翻译一下题干
leetcode 的题干就宛如十年前的机翻,要有多脑残多脑残。
这个问题的实用场景就是:实际上咱们的🌳是保存在机器的RAM的,如果断电了这棵树就嗝屁了。
但是我们想把这棵树永久的保存在你的心间
所以就想一个办法把它变成可持久化存储的东西,比如字符串。
再进一步说人话:
把树变成字符串。
分析
很简单我们会想到把🌳遍历一遍就可以了。
对,前中后序都完全ojbk,这不是这道题的题眼
我们看题干的示例,就是把所有树都当作完全二叉树来处理,如果没有的都存储成null。这样确实直接遍历一遍就得到字符串了,但是回去就很麻烦。
现在以先序为例,有两个问题:
怎么判断这个树的节点的位置:比如12345为什么是如图的样子而不是全都在一条枝上。
于是我们有了这样的想法如果这个节点为空,我们要用符号来它为空
比如,如果是空就在后边加“#”,还是这棵树,先序遍历
12##345,2的后边连续两个#,说明是叶子节点了。确实没有另外的可能性。
也就是说字符串返回成树这个映射关系,也唯一了。
下边直接上代码。
树转字符串:先序,空就加#
与此同时每一位都加_
字符串转数:先通过分隔符_将字符串分隔并存入数组。
再将它的值存入队列。
再先序遍历放回去,如果取出来的数组是#,那么这个节点为空。否则这个节点的值就是取出来的值。在递归一下就出来了
存入“_”完全是为了再回到树的时候有个分隔符好放一点
Java代码
我的代码:
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root==null){
return "#_";
}
String res = root.val + "_";
res += serialize(root.left);
res += serialize(root.right);
return res;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String []values = data.split("_");
Queue<String> queue = new LinkedList<String>();
for(int i = 0; i!=values.length; i++){
queue.offer(values[i]);
}
return generate(queue);
}
public TreeNode generate(Queue<String> queue){
String value = queue.poll();
if(value.equals("#")){
return null;
}
TreeNode root = new TreeNode(Integer.valueOf(value));
root.left = generate(queue);
root.right = generate(queue);
return root;
}
}
大佬们的代码:
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
public class Codec {
private TreeNode node;
public String serialize(TreeNode root) {
node = root;
return null;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
return node;
}
}
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
this.root = root;
return "(* ̄︶ ̄)";
}
public TreeNode root = null;
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
int i = 0;
do{
int j = 1024 * i;
i++;
}
while(i < 1024 * 1024);
return root;
}
}
public class Codec {
public String serialize(TreeNode root) {
StringBuffer sb = new StringBuffer();
dfs_s(root,sb);
return String.valueOf(sb);
}
private void dfs_s(TreeNode root, StringBuffer sb) {
if (root == null){
sb.append("#,");
return;
}
sb.append(root.val + ",");
dfs_s(root.left,sb);
dfs_s(root.right,sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
int[] u = {0};
return dfs_d(data,u);
}
private TreeNode dfs_d(String data, int[] u) {
//if (u == data.length())
if (data.charAt(u[0]) == '#'){
u[0] += 2;
return null;
}
int t= 0;
boolean is_minus = false;
if (data.charAt(u[0]) == '-'){
is_minus = true;
u[0]++;
}
while (data.charAt(u[0]) != ','){
t = t*10 +data.charAt(u[0]) - '0';
u[0]++;
}
u[0]++;
if (is_minus) t *= -1;
TreeNode root = new TreeNode(t);
root.left = dfs_d(data,u);
root.right = dfs_d(data,u);
return root;
}
}
总结
这道题其实很综合,有几个要点:
1.树🌳天然递归
2.遍历就能把树转成字符串
3.字符串回树怎么标记位置使其唯一
代码思路参考:
https://blog.csdn.net/yysave/article/details/90024200