树的序列化与那不太一样的反序列化方法
序列化二叉树
http://www.nowcoder.com/questionTerminal/cf7e25aa97c04cc1a68c8f040e71fb84
序列化:选择前序遍历,与大多数答案相同,递归,在字符串后面拼接。
反序列化:作为菜鸡,脑子发热,就想用非递归的方法写,由于没有指向父节点的指针,于是采用了一个栈存储路径上的节点。遍历字符串每一个字符,用一个整形变量标记value的首字符下标。
不太一样的地方:由于题目没给测试例子,我以为序列化时空节点直接是'#',看到众多简洁的答案的序列化方法中空节点是用"#,"代表,感觉我被坑了emmm,由于我的序列化方法空节点直接是"#",导致不能直接用字符串的split操作获取每个节点的值,必须对字符串每个字符遍历唉。。
public class Solution {
String Serialize(TreeNode root) {
if(root == null ) return "#";
String result = String.valueOf(root.val).concat("!");
return result.concat(Serialize(root.left)).concat(Serialize(root.right)); //先序遍历
}
TreeNode Deserialize(String str) {
if( "#".equals(str)) return null;
int splitIndex = 0; //标记字符串的value开始的下标
Stack<TreeNode> parents = new Stack<>();
TreeNode root = null;
//找到 !前的value 创建节点
for(int i = 0 ; i < str.length() ; i++) {
if(str.charAt(i) == '!') {
int value = Integer.parseInt(str.substring(splitIndex, i));
TreeNode node = new TreeNode(value);
if(! parents.empty()) {
TreeNode parent = parents.peek();
if( parent.left == null && str.charAt(splitIndex - 1) != '#' ) {
parent.left = node; //父节点的左孩子不应是叶子,给他找个左孩子
}else if(parent.right == null ){
parent.right = node;
parents.pop(); //这个父节点的右孩子都找到了直接pop走
}
}
if(root == null) {
root = node; //前序序列,赋予第一个创建的节点为根节点
}
parents.push(node); //添加路径上的节点进栈
splitIndex = i + 1;
}
if(str.charAt(i) == '#') {
if(i < str.length() - 1 && str.charAt(i + 1) == '#'){
//说明栈顶父节点孩子皆为叶子,直接pop走
if(! parents.empty()) parents.pop();
splitIndex = i + 2;
} else {
if(splitIndex < i && !parents.empty() && parents.peek().left != null){
//防止双#中的第二#导致无辜父节点被pop
if(! parents.empty()) parents.pop();//说明栈顶父节点已有左孩子,右孩子为叶子,pop走
}
splitIndex = i + 1;
}
}
}
return root;
}
}
查看12道真题和解析