题目链接:
力扣https://leetcode.cn/problems/serialize-and-deserialize-bst/
【分析】这道题和297. 二叉树的序列化与反序列化其实可以一样做,通过保存null节点来保存树的结构信息,但是这个是二叉搜索树,自带中序遍历的结果,而通过前序和中序遍历是可以还原出树的结构的,于是这里可以不保存null节点的信息,节省一些空间。
那么如何根据先序遍历和排序规则还原呢,以样例一为🌰
先序是2,1,3;2肯定是根节点,那么如何确定左右子树到哪里呢,根据二叉搜索树的性质,左子树的节点都比根节点的值小,所以找到第一个>根节点的值的下标idx,递归构建[1,idx - 1]和[idx,n-1]分别作为left和right即可。
public class Codec {
public List<Integer> list = new ArrayList();
public int[] arr;
public void dfs(TreeNode node){
if(node == null) return;
list.add(node.val);
dfs(node.left);
dfs(node.right);
}
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
dfs(root);
StringBuilder sb = new StringBuilder();
for(var i = 0; i < list.size(); i++){
if(i != 0) sb.append(',');
sb.append(list.get(i));
}
return sb.toString();
}
public int binarySearch(int left, int right, int target){
int mid;
while(left <= right){
mid = (left + right) >>> 1;
if(arr[mid] > target) right = mid - 1;
else left = mid + 1;
}
return left;
}
public TreeNode f(int left, int right){
if(left > right) return null;
if(left == right) return new TreeNode(arr[left]);
TreeNode root = new TreeNode(arr[left]);
int idx = binarySearch(left + 1, right, arr[left]);
root.left = f(left + 1, idx - 1);
root.right = f(idx, right);
return root;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if(data == "") return null;
String[] strs = data.split(",");
int n = strs.length;
int[] arr = new int[n];
for(var i = 0; i < n; i++) arr[i] = Integer.parseInt(strs[i]);
this.arr = arr;
return f(0, n - 1);
}
}