序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化 二叉搜索树 。 对序列化/反序列化算法的工作方式没有限制。 您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
示例 1:
输入:root = [2,1,3]
输出:[2,1,3]
示例 2:
输入:root = []
输出:[]
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/serialize-and-deserialize-bst
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
方法一:递归,时间和空间复杂度O(N)
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
traverse(root, sb);
return sb.toString();
}
final String SEP = ",";
private void traverse(TreeNode root, StringBuilder sb) {
if (root == null) {
return;
}
sb.append(root.val).append(SEP);
traverse(root.left, sb);
traverse(root.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.isEmpty()) {
return null;
}
List<Integer> list = new ArrayList<>();
for (String node : data.split(SEP)) {
list.add(Integer.parseInt(node));
}
return deserialize(list, 0, list.size() - 1);
}
private TreeNode deserialize(List<Integer> list, int lo, int hi) {
if (lo > hi) {
return null;
}
TreeNode root = new TreeNode(list.get(lo));
int k = lo + 1;
//利用BST特性,左子树小于根节点值,找到分界点
while (k <= hi && list.get(k) < list.get(lo)) {
k++;
}
root.left = deserialize(list, lo + 1, k - 1);
root.right = deserialize(list, k, hi);
return root;
}
}
方法二:利用栈遍历,时间和空间复杂度O(N)
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
traverse(root, sb);
return sb.toString();
}
final String SEP = ",";
private void traverse(TreeNode root, StringBuilder sb) {
if (root == null) {
return;
}
sb.append(root.val).append(SEP);
traverse(root.left, sb);
traverse(root.right, sb);
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.isEmpty()) {
return null;
}
String[] preOrder = data.split(SEP);
TreeNode root = new TreeNode(Integer.parseInt(preOrder[0]));
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
for (int i = 1; i < preOrder.length; i++) {
int val = Integer.parseInt(preOrder[i]);
TreeNode node = new TreeNode(val);
//小于栈顶元素的值,说明应该在栈顶元素的左子树
if (stack.peek().val > val) {
stack.peek().left = node;
} else {
//大于栈顶元素的值,我们要找到当前元素的父节点
TreeNode parent = stack.peek();
//栈从栈底到栈顶是递减的
while (!stack.isEmpty() && stack.peek().val < val) {
parent = stack.pop();
}
parent.right = node;
}
stack.push(node);
}
return root;
}
}