Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
Example:
You may serialize the following tree: 1 / 2 3 / 4 5 as"[1,2,3,null,null,4,5]"
Clarification: The above format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
二叉树的序列化和反序列化。题目即是题意,序列化是需要把二叉树convert成一个字符串;同时这个字符串也可以被convert回对应的二叉树。影子题449题。这道题有两种思路,一种是BFS层序遍历,一种是preorder前序遍历。
首先是BFS。序列化的部分是按照level order traversal的思路遍历树的节点。如果当前节点为NULL则存入"null";若不是,则正常存入当前节点,再遍历当前节点的左孩子和右孩子。记得存入每个节点之后加一个空格,这样方便接下来的反序列。
反序列化是将一个字符串的input转换成树的结构。首先将字符串中第一个node拿到,当做根节点。之后还是根据BFS的思路遍历input,如果不为"null"则做成一个节点并加入queue;但是这里反序列化可以跳过null,不需要把null也转换成一个空的节点放入二叉树。
时间O(n)
空间O(n)
Java实现
1 public class Codec { 2 3 // Encodes a tree to a single string. 4 public String serialize(TreeNode root) { 5 if (root == null) 6 return ""; 7 StringBuilder res = new StringBuilder(); 8 Queue<TreeNode> queue = new LinkedList<>(); 9 queue.offer(root); 10 while (!queue.isEmpty()) { 11 TreeNode cur = queue.poll(); 12 if (cur == null) { 13 res.append("null "); 14 continue; 15 } 16 res.append(cur.val + " "); 17 queue.offer(cur.left); 18 queue.offer(cur.right); 19 } 20 return res.toString(); 21 } 22 23 // Decodes your encoded data to tree. 24 public TreeNode deserialize(String data) { 25 if (data == "") 26 return null; 27 String[] str = data.split(" "); 28 TreeNode root = new TreeNode(Integer.parseInt(str[0])); 29 Queue<TreeNode> queue = new LinkedList<>(); 30 queue.offer(root); 31 for (int i = 1; i < str.length; i++) { 32 TreeNode cur = queue.poll(); 33 if (!str[i].equals("null")) { 34 cur.left = new TreeNode(Integer.parseInt(str[i])); 35 queue.offer(cur.left); 36 } 37 i++; 38 if (!str[i].equals("null")) { 39 cur.right = new TreeNode(Integer.parseInt(str[i])); 40 queue.offer(cur.right); 41 } 42 } 43 return root; 44 } 45 } 46 47 // Your Codec object will be instantiated and called as such: 48 // Codec codec = new Codec(); 49 // codec.deserialize(codec.serialize(root));
JavaScript实现
1 /** 2 * Encodes a tree to a single string. 3 * 4 * @param {TreeNode} root 5 * @return {string} 6 */ 7 var serialize = function (root) { 8 let stack = []; 9 let serialize = []; 10 if (root == null) return []; 11 stack.push(root); 12 while (stack.length > 0) { 13 let cur = stack.shift(); 14 serialize.push(cur ? cur.val : null); 15 if (cur != null) { 16 stack.push(cur.left); 17 stack.push(cur.right); 18 } 19 } 20 return serialize; 21 }; 22 23 var deserialize = function (data) { 24 if (data[0] == null) return null; 25 let node = new TreeNode(data.shift()); 26 let queue = [node]; 27 while (queue.length > 0) { 28 let node = queue.shift(); 29 left = data.shift(); 30 right = data.shift(); 31 node.left = (left == null) ? null : new TreeNode(left); 32 node.right = (right == null) ? null : new TreeNode(right); 33 if (node.left != null) { 34 queue.push(node.left); 35 } 36 if (node.right != null) { 37 queue.push(node.right); 38 } 39 } 40 return node; 41 }; 42 43 /** 44 * Your functions will be called as such: 45 * deserialize(serialize(root)); 46 */
再来是前序遍历的思路。既然是前序遍历,那么还是先处理当前节点,再处理他的左孩子和右孩子。序列化的部分,还是需要对空节点记录,我这里还是记录成"null" + 一个空格,然后调用helper函数递归处理左孩子和有孩子。反序列化的时候,除了一开始需要把data分开,同时需要把data分开的内容放入一个queue,这样每弹出一个元素,我们还是可以通过一个helper函数递归处理左孩子和右孩子节点。这个做法比之前BFS的做法稍稍快一点。
时间O(n)
空间O(n)
Java实现
1 /** 2 * Definition for a binary tree node. 3 * public class TreeNode { 4 * int val; 5 * TreeNode left; 6 * TreeNode right; 7 * TreeNode(int x) { val = x; } 8 * } 9 */ 10 public class Codec { 11 12 // Encodes a tree to a single string. 13 public String serialize(TreeNode root) { 14 StringBuilder sb = new StringBuilder(); 15 helper(root, sb); 16 return sb.toString(); 17 } 18 19 private void helper(TreeNode root, StringBuilder sb) { 20 if (root == null) { 21 // sb.append("#").append(","); 22 sb.append("null "); 23 } else { 24 sb.append(root.val).append(" "); 25 helper(root.left, sb); 26 helper(root.right, sb); 27 } 28 } 29 30 // Decodes your encoded data to tree. 31 public TreeNode deserialize(String data) { 32 // corner case 33 if (data == null) { 34 return null; 35 } 36 // normal case 37 String[] strs = data.split(" "); 38 Queue<String> queue = new LinkedList<>(); 39 Collections.addAll(queue, strs); 40 return helper(queue); 41 } 42 43 private TreeNode helper(Queue<String> queue) { 44 if (queue.isEmpty()) { 45 return null; 46 } 47 String s = queue.poll(); 48 if (s.equals("null")) { 49 return null; 50 } 51 TreeNode root = new TreeNode(Integer.parseInt(s)); 52 root.left = helper(queue); 53 root.right = helper(queue); 54 return root; 55 } 56 } 57 58 // Your Codec object will be instantiated and called as such: 59 // Codec ser = new Codec(); 60 // Codec deser = new Codec(); 61 // TreeNode ans = deser.deserialize(ser.serialize(root));
相关题目
297. Serialize and Deserialize Binary Tree
428. Serialize and Deserialize N-ary Tree