题目描述
请实现两个函数,分别用来序列化和反序列化二叉树。
示例:
思路一:
序列化的过程是把一棵树转化成一个字符串,而且要去除末尾连续的“null"。二叉树在字符串中的状态就是层序遍历二叉树的序列,但是因为需要去除字符串末尾的值为 “null” 连续字符串,必须先把所有的序列用linkedList存下来,遍历完成后去除 list 中末尾的连续“null", 最后把 list 输出即可
反序列化的过程就是把一个层序遍历的序列转换成一个棵树,所以将输入字符去除首尾的括号后按照“, ”分割为字符串数组,按照层序遍历建树即可。每次从队列中取出一个结点,再从数组中取出两个值作为该结点的左右孩子结点,然后将左右孩子结点入队。
1 public class Codec { 2 3 // Encodes a tree to a single string. 4 public String serialize(TreeNode root) { 5 // 层序遍历打印树 6 if(root == null){ 7 return "[]"; 8 } 9 10 LinkedList<String> list = new LinkedList<>(); 11 Queue<TreeNode> queue = new LinkedList<>(); 12 queue.offer(root); 13 while(!queue.isEmpty()){ 14 TreeNode node = queue.poll(); 15 String val = (node == null ? "null" : String.valueOf(node.val)); 16 list.addLast(val); 17 if(node != null){ 18 queue.offer(node.left); 19 queue.offer(node.right); 20 } 21 } 22 23 // 去除末尾的连续的“null” 24 int index = list.size() - 1; 25 for(; index >= 0; index--){ 26 if(list.getLast().equals("null")){ 27 list.removeLast(); 28 } 29 } 30 31 return list.toString(); 32 } 33 34 // Decodes your encoded data to tree. 35 public TreeNode deserialize(String data) { 36 if(data == null || data.equals("[]")){ 37 return null; 38 } 39 // 分割字符串 40 String[] nodes = data.substring(1, data.length()-1).split(", "); 41 // 层序遍历建树 42 TreeNode root = new TreeNode(Integer.parseInt(nodes[0])); 43 Queue<TreeNode> queue = new LinkedList<>(); 44 queue.offer(root); 45 int i = 0; 46 int len = nodes.length; 47 while(!queue.isEmpty()){ 48 TreeNode node = queue.poll(); 49 if(i + 1 < len && !"null".equals(nodes[i + 1])){ 50 node.left = new TreeNode(Integer.parseInt(nodes[i + 1])); 51 queue.offer(node.left); 52 } 53 if(i + 2 < len && !"null".equals(nodes[i + 2])){ 54 node.right = new TreeNode(Integer.parseInt(nodes[i + 2])); 55 queue.offer(node.right); 56 } 57 i += 2; 58 } 59 return root; 60 } 61 }
leetcode 执行用时:32 ms > 16.13%, 内存消耗:40.8 MB > 62.20%
复杂度分析:
时间复杂度:
serialize() 方法:O(n)。遍历所有树的所有结点时间花费为O(n),后面遍历list 删除连续 “null” 的时间花费也是O(n), 所以最终的时间复杂度为O(n)。
deserialize() 方法:O(n)。层序遍历建树的过程中遍历了nodes[]数组,nodes[]数组的大小就是树的结点个数,所以该方法的时间复杂度为O(n)。
空间复杂度:
serialize() 方法:O(n)。其中包含了队列的开销和 list 集合的开销,list集合因为需要存下所有结点,所以花费的空间为O(n), 队列只需要存储一层的结点,所以复杂度最大为O(n/2), 所以该方法的空间复杂度为O(n)。
deserialize() 方法:O(n)。同样需要一个数组把所有的结点先存储下来,这个开销是O(n), 队列的开销也是O(n/2), 所以这个方法的空间复杂度也为O(n)。