树的序列化与那不太一样的反序列化方法
序列化二叉树
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; } }