思路
看到題目給的例子時,我以爲在序列化時時將整棵樹作爲滿二叉樹來序列化,但是在測試時發現並不是,它只是判斷每個節點的左右子樹是否爲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));
}