[LeetCode] 449. Serialize and Deserialize BST
Serialization is 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 search tree. There is no restriction on how your serialization/deserialization algorithm should work. You need to ensure that a binary search tree can be serialized to a string, and this string can be deserialized to the original tree structure.
The encoded string should be as compact as possible.
For example, you may serialize the following 3-ary
tree
as [1 [3[5 6] 2 4]]
. Note that this is just an example, you do not necessarily need to follow this format.
Or you can follow LeetCode's level order traversal serialization format, where each group of children is separated by the null value.
For example, the above tree may be serialized as [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
.
You do not necessarily need to follow the above suggested formats, there are many more different formats that work so please be creative and come up with different approaches yourself.
Constraints:
- The height of the n-ary tree is less than or equal to
1000
- The total number of nodes is between
[0, 10^4]
- Do not use class member/global/static variables to store states. Your encode and decode algorithms should be stateless.
二叉搜索树的序列化和反序列化。
题意跟297题很接近,事实上297题的代码可以直接抄过来,也能通过。参见如下代码。思路还是BFS层序遍历,注意因为有的节点有可能是空的,所以序列化的时候也需要记录,否则还原的时候,就会丢失信息。
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 if (root == null) { 15 return ""; 16 } 17 StringBuilder res = new StringBuilder(); 18 Queue<TreeNode> queue = new LinkedList<>(); 19 queue.offer(root); 20 while (!queue.isEmpty()) { 21 TreeNode cur = queue.poll(); 22 if (cur == null) { 23 res.append("null "); 24 continue; 25 } 26 res.append(cur.val + " "); 27 queue.offer(cur.left); 28 queue.offer(cur.right); 29 } 30 return res.toString(); 31 } 32 33 // Decodes your encoded data to tree. 34 public TreeNode deserialize(String data) { 35 if (data == "") { 36 return null; 37 } 38 String[] str = data.split(" "); 39 TreeNode root = new TreeNode(Integer.parseInt(str[0])); 40 Queue<TreeNode> queue = new LinkedList<>(); 41 queue.offer(root); 42 for (int i = 1; i < str.length; i++) { 43 TreeNode cur = queue.poll(); 44 if (!str[i].equals("null")) { 45 cur.left = new TreeNode(Integer.parseInt(str[i])); 46 queue.offer(cur.left); 47 } 48 i++; 49 if (!str[i].equals("null")) { 50 cur.right = new TreeNode(Integer.parseInt(str[i])); 51 queue.offer(cur.right); 52 } 53 } 54 return root; 55 } 56 } 57 58 // Your Codec object will be instantiated and called as such: 59 // Codec codec = new Codec(); 60 // codec.deserialize(codec.serialize(root));
这道题相比于297题唯一的不同是297题是对普通的二叉树做操作,用层序遍历比较方便;本题是BST,因为BST的左子树比根节点小,右子树比根节点大,所以用前序遍历也可以。因为BST的前序遍历的结果反过来是可以确定唯一一个二叉树的结构的。
序列化的思路如下,用前序遍历preorder,会得到一个无序的数组,数组内容是无序的,但是基本遵照的是根 - 左 - 右的顺序。
反序列化的部分就有点意思了,反序列化需要先拿到queue中的第一个节点,此节点为树的根节点;对于之后的所有节点,需要判断他们到底是大于还是小于根节点,将较小的节点用另一个queue存放,这样左右子树上的节点就可以被分开了。用这样的递归完成树的构建。
根据这个discussion,一个BST前序遍历的结果应该长类似这样,所以可以用root节点来挑出分别属于左子树和右子树的节点,然后递归建立整棵树。
rootValue (<rootValue) (<rootValue) (<rootValue) |separate line| (>rootValue) (>rootValue)
时间O(n)
空间O(n),序列化用到了stack,反序列化用到了queue和递归的栈空间
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 Stack<TreeNode> stack = new Stack<>(); 9 stack.push(root); 10 while (!stack.isEmpty()) { 11 TreeNode cur = stack.pop(); 12 res.append(cur.val + " "); 13 if (cur.right != null) { 14 stack.push(cur.right); 15 } 16 if (cur.left != null) { 17 stack.push(cur.left); 18 } 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 Queue<Integer> queue = new LinkedList<>(); 29 for (String s : str) { 30 queue.offer(Integer.parseInt(s)); 31 } 32 return getNode(queue); 33 } 34 35 public TreeNode getNode(Queue<Integer> queue) { 36 if (queue.isEmpty()) 37 return null; 38 TreeNode root = new TreeNode(queue.poll()); 39 Queue<Integer> smallerQ = new LinkedList<>(); 40 while (!queue.isEmpty() && queue.peek() < root.val) { 41 smallerQ.offer(queue.poll()); 42 } 43 root.left = getNode(smallerQ); 44 root.right = getNode(queue); 45 return root; 46 } 47 } 48 49 // Your Codec object will be instantiated and called as such: 50 // Codec codec = new Codec(); 51 // 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 preorder = []; 9 let dfs = function (node) { 10 if (node == null) return; 11 preorder.push(node.val); 12 dfs(node.left); 13 dfs(node.right); 14 } 15 dfs(root); 16 return preorder.join(','); 17 }; 18 19 /** 20 * Decodes your encoded data to tree. 21 * 22 * @param {string} data 23 * @return {TreeNode} 24 */ 25 var deserialize = function (data) { 26 if (data == '') return null; 27 let preorder = data.split(','); 28 let recur = function (lower, upper) { 29 if (Number(preorder[0]) < lower || Number(preorder[0]) > upper) { 30 return null; 31 } 32 if (preorder.length == 0) return null; 33 let root = new TreeNode(preorder.shift()); 34 root.left = recur(lower, root.val); 35 root.right = recur(root.val, upper); 36 return root; 37 } 38 return recur(-Infinity, Infinity); 39 }; 40 41 /** 42 * Your functions will be called as such: 43 * deserialize(serialize(root)); 44 */
相关题目
297. Serialize and Deserialize Binary Tree
428. Serialize and Deserialize N-ary Tree