297. Serialize and Deserialize Binary Tree
用String表示BinaryTree,然后在通过String还原刚才的BinaryTree.
其实我感觉LeetCode一直用的一层一层的表达方式就挺好的,通过BFS实现的。
这里如果是DFS的话,那么就pre/in/post选一种,应该都可以。
有2个需要记录,1个是每个NODE的值,1个是结构,结构可以通过#来标记NULL.
如果都只有一位数,直接一个STRING就能搞定,否则还得用别的符号区分NODE和NODE,随便找个就行,我傻不拉几的用.区分,然后split的时候又他妈写成split(".")。。
还原的时候先通过刚才订的符号分割,然后根据pre/in/post来加到有顺序的数据结构了就行了,stack或者queue根据需要。
public class Codec
{
// Encodes a tree to a single string.
public String serialize(TreeNode root)
{
if(root == null) return "#";
StringBuilder sb = new StringBuilder();
helper(root,sb);
return sb.toString();
}
public void helper(TreeNode root,StringBuilder sb)
{
if(root == null)
{
sb.append("#.");
return;
}
sb.append(root.val).append(".");;
helper(root.left,sb);
helper(root.right,sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data)
{
String[] str = data.split("\\.");
Queue<String> q = new LinkedList<String>();
for(String n: str) q.add(n);
return awesome(q);
}
public TreeNode awesome(Queue<String> q)
{
String tempStr = q.poll();
if(tempStr.equals("#")) return null;
TreeNode root = new TreeNode(Integer.valueOf(tempStr));
if(q.size() != 0) root.left = awesome(q);
if(q.size() != 0) root.right = awesome(q);
return root;
}
}
leetcode见过2道还原binary tree的题,给你in-order pre-order post-order其中2个,让你还原。
这里也可以,选其中2个方式各遍历一次,弄成1个Sring。还原的时候String平均分两半,剩下就和那俩题一样。坏处是时间上比较麻烦,空间说不定能省= =
代码就不写了。
二刷。
这个题居然是二刷,完全没印象。。。
二刷的开始,decode用array做的,传index传乱了几次,后来换成Queue了。。
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "X#";
StringBuilder sb = new StringBuilder();
encode(root, sb);
return sb.toString();
}
public void encode(TreeNode root, StringBuilder sb) {
if (root == null) {
sb.append("X#");
} else {
sb.append(root.val).append("#");
encode(root.left, sb);
encode(root.right, sb);
}
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
Queue<String> q = new LinkedList<>();
q.addAll(Arrays.asList(data.split("#")));
return decode(q);
}
public TreeNode decode(Queue<String> q) {
if(q.isEmpty()) return null;
String s = q.poll();
if (s.equals("X")) {
return null;
} else {
TreeNode res = new TreeNode(Integer.valueOf(s));
res.left = decode(q);
res.right = decode(q);
return res;
}
}
}
回头发现这个题居然做过,然后一刷也是用的Queue,唯一的进步是把
for(String s: str) q.offer(s);
写成了
q.addAll(Arrays.asList(str));
好好分析下这个题。
用的思想其实是通过添加特殊符号把整个树补完整,否则[1,2]2是左是右都没法确定,言外之意是没法确定结构。
DFS和BFS应该都可以。
感觉BFS的问题就是要分层= =...
按这个思路想了一下,得记录上一层,或者得知道下一层的位置,比较麻烦。又或者可以理解为,得有个queue来保留上一层。
试试。。
搞定= =按层encode,记得补全NULL。
decode的时候,用一个Queue来记录上一层,每次添加左边添加右边,NULL就不放到Queue里就行了。。
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) return "X#";
StringBuilder sb = new StringBuilder();
TreeNode temp = null;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while (!q.isEmpty()) {
temp = q.poll();
if (temp == null) {
sb.append("X#");
} else {
sb.append(temp.val + "#");
q.offer(temp.left);
q.offer(temp.right);
}
}
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data.equals("X#")) return null;
String[] s = data.split("#");
TreeNode root = new TreeNode(Integer.valueOf(s[0]));
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
TreeNode temp = null;
for (int i = 1; i < s.length; ) {
temp = q.poll();
if (s[i].equals("X")) {
temp.left = null;
} else {
temp.left = new TreeNode(Integer.valueOf(s[i]));
q.offer(temp.left);
}
i ++;
if (s[i].equals("X")) {
temp.right = null;
} else {
temp.right = new TreeNode(Integer.valueOf(s[i]));
q.offer(temp.right);
}
i ++;
}
return root;
}
}
Operation | Time | Space |
---|---|---|
DFS Encode | O(N) | O(lgN) + O(N) |
DFS Decode | O(N) | O(lgN) + O(N) |
BFS Eecode | O(N) | O(N) + O(N) |
BFS Decode | O(N) | O(N) + O(N) |
什么乱七八糟的。。。破表格。反正基本就是O(N)
有的时候多个stack的内存空间,有时候多个Queue,不复杂。。