题目:请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
你可以将以下二叉树:
1
/ \
2 3
/ \
4 5
序列化为 “[1,2,3,null,null,4,5]”
深度优先搜索,时间复杂度o(n),空间复杂度o(n)
序列化:前序遍历,使用StringBuilder保存节点值
- 采用前序遍历的方式,对二叉树的各个节点进行序列化,每个节点值存入一个Stringbuilder中
存放时,需要在节点值后添加一个!表示节点结束,如果出现了null节点则用#!表示
// Encodes a tree to a single string.public String serialize(TreeNode root) {// 存放序列化后的结果StringBuilder res = new StringBuilder();helpSerialize(root,res);return res.toString();}public void helpSerialize(TreeNode root,StringBuilder res){if(root != null){res.append(root.val).append("!");}else{res.append("#!");return;}helpSerialize(root.left,res);helpSerialize(root.right,res);}
反序列化:前序遍历,把StringBuilder中保存的值分割后,重新组成新树
“!”分割成多个字符串,且设置下标index
- 每次遇到#时,代表为空,此时index++,且到下一次递归(此处也可以不用下标index,而将数据放到队列中,每次取出队头元素)
最后用当前值创建新节点,且继续递归左右子树
Integer index = 0;// 反序列化时,当作String数组的下标// Decodes your encoded data to tree.public TreeNode deserialize(String data) {if (data == null || data.length() == 0) return null;// 拿出有效数据String[] split = data.split("!");return helpDeserialize(split);}// 全局下标public TreeNode helpDeserialize(String[] strings){if(strings[index].equals("#")){index++;return null;}if(strings.length == index)return null;// 当前值作为节点已经被用,index++到达下一个需要反序列化的值TreeNode node = new TreeNode(Integer.valueOf(strings[index++]));// 先左node.left = helpDeserialize(strings);// 再右node.right = helpDeserialize(strings);return node;}// 队列形式public TreeNode deserialize(String data) {if(data.isEmpty())return null;Deque<String> deque = new LinkedList<>(Arrays.asList(data.split("!")));return helpDeserialize(deque);}public TreeNode helpDeserialize(Deque<String> deque){String str = deque.poll();if(str.equals("#")){return null;}TreeNode node = new TreeNode(Integer.parseInt(str));node.left = helpDeserialize(deque);node.right = helpDeserialize(deque);return node;}}
广度优先搜索,时间复杂度o(n),空间复杂度o(n)
序列化:使用队列,按照正常方式,使用StringBuilder保存节点值,如果遇到空,则保存为#!
// Encodes a tree to a single string.public String serialize(TreeNode root) {if(root == null)return "";StringBuilder sb = new StringBuilder();Deque<TreeNode> deque = new LinkedList<>();deque.add(root);while(!deque.isEmpty()){int sz = deque.size();for(int i = 0 ; i < sz ; i++){TreeNode node = deque.poll();if(node == null){sb.append("#!");continue;}sb.append(node.val).append("!");deque.add(node.left);deque.add(node.right);}}return sb.toString();}
反序列化:前序遍历,把StringBuilder中保存的值分割后,将首个值加入到队列中,然后继续依次根据左右节点加入队列,最后重新组成新树
// Decodes your encoded data to tree. public TreeNode deserialize(String data) { if(data.isEmpty()) return null; String [] datas = data.split("!"); Deque<TreeNode> deque = new LinkedList<>(); TreeNode root = new TreeNode(Integer.parseInt(datas[0])); deque.add(root); for(int i = 1 ; i < datas.length ; i++){ TreeNode node = deque.poll(); if(!datas[i].equals("#")){ TreeNode left = new TreeNode(Integer.parseInt(datas[i])); node.left = left; deque.add(left); } if(!datas[++i].equals("#")){ TreeNode right = new TreeNode(Integer.parseInt(datas[i])); node.right = right; deque.add(right); } } return root; }
