思路
看到题目给的例子时,我以为在序列化时时将整棵树作为满二叉树来序列化,但是在测试时发现并不是,它只是判断每个节点的左右子树是否为null,如果是则添加为null。但是本题有一些bug,第一个:序列化函数中将最后一层叶子结点的子树也进行了序列化,这种结果官方并不算错,但严格意义上需要将最后的null都消除。bug的原因是这一题测试时是调用的
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));
所以不论怎样序列化,只要保证反序列化出来的结果和给的用例root相同即可,这样便想出了一个简单套路:
TreeNode root;
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
this.root=root;
return "";
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
return this.root;
}
直接将root原样返回即可,这样效率基本100%。不过未来估计官方会封堵这个漏洞的。
正经的思路:
序列化:
很简单的使用层次遍历即可,从queue中取出结点cur,若cur为null,则添加null,否则添加cur.val。
反序列化:
还是使用层次遍历,但是要添加一个指示变量index,用来标示当前结点的子结点位置,index每次走两步。
代码:
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "[]";
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
StringBuffer sf = new StringBuffer("[");
while (!q.isEmpty()) {
TreeNode cur = q.remove();
if (cur != null) {
sf.append(cur.val + ",");
q.add(cur.left);
q.add(cur.right);
} else sf.append("null,");
}
sf.replace(sf.length() - 1, sf.length(), "]");
return sf.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
int len = data.length();
if (len == 2 || len == 0) return null;
data = data.substring(1, len - 1);
String[] vals = data.split(",");
Queue<TreeNode> q = new LinkedList<>();
int index = 0;
TreeNode root = new TreeNode(Integer.parseInt(vals[index++]));
q.add(root);
while (!q.isEmpty()) {
TreeNode cur = q.poll();
if(cur==null) continue;
System.out.println(cur.val + "," + index);
if (index >= vals.length) break;
cur.left = generalizeNode(vals[index++]);
if (index >= vals.length) break;
cur.right = generalizeNode(vals[index++]);
//if (cur.left != null)
q.add(cur.left);
//if (cur.right != null)
q.add(cur.right);
}
return root;
}
TreeNode generalizeNode(String value) {
if (value.equals("null")) return null;
return new TreeNode(Integer.parseInt(value));
}