449. 序列化和反序列化二叉搜索树
问题描述
序列化是将数据结构或对象转换为一系列位的过程,以便它可以存储在文件或内存缓冲区中,或通过网络连接链路传输,以便稍后在同一个或另一个计算机环境中重建。
设计一个算法来序列化和反序列化二叉搜索树。对序列化/反序列化算法的工作方式没有限制。您只需确保二叉搜索树可以序列化为字符串,并且可以将该字符串反序列化为最初的二叉搜索树。
编码的字符串应尽可能紧凑。
示例:
输入: root = [2,1,3]
输出: [2,1,3]
输入: root = []
输出: []
说明: 你的 Codec 类需要实现 serialize 和 deserialize 两个方法
算法思路
利用BST性质的前序遍历法:
- 序列化:使用前序遍历(根-左-右),将节点值用分隔符连接成字符串
- 反序列化:利用BST性质,递归重建树
- 第一个值是根节点
- 小于根节点的值构成左子树
- 大于根节点的值构成右子树
- 由于BST的有序性,不需要存储null节点,可以重建唯一BST
关键:
- BST的前序遍历 + BST性质可以唯一确定树结构
- 不需要像普通二叉树那样存储null节点,节省空间
- 反序列化时使用范围限制(min, max)确保BST性质
代码实现
方法一:前序遍历 + 范围限制
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
/**
* 序列化二叉搜索树
* 使用前序遍历,将节点值用逗号分隔
*
* @param root BST根节点
* @return 序列化后的字符串
*/
public String serialize(TreeNode root) {
if (root == null) {
return "";
}
StringBuilder sb = new StringBuilder();
preorder(root, sb);
// 移除最后一个分隔符
if (sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
/**
* 前序遍历
*/
private void preorder(TreeNode node, StringBuilder sb) {
if (node == null) {
return;
}
// 添加当前节点值
sb.append(node.val).append(",");
// 遍历左子树
preorder(node.left, sb);
// 遍历右子树
preorder(node.right, sb);
}
/**
* 反序列化二叉搜索树
* 利用BST性质和前序遍历重建树
*
* @param data 序列化字符串
* @return 重建的BST根节点
*/
public TreeNode deserialize(String data) {
if (data == null || data.length() == 0) {
return null;
}
// 将字符串分割为整数数组
String[] values = data.split(",");
int[] nums = new int[values.length];
for (int i = 0; i < values.length; i++) {
nums[i] = Integer.parseInt(values[i]);
}
// 使用索引数组来传递引用
int[] index = {
0};
return buildBST(nums, index, Integer.MIN_VALUE, Integer.MAX_VALUE);
}
/**
* 递归构建BST
*
* @param nums 前序遍历的值数组
* @param index 当前处理位置(使用数组传递引用)
* @param min 当前子树允许的最小值
* @param max 当前子树允许的最大值
* @return 构建的子树根节点
*/
private TreeNode buildBST(int[] nums, int[] index, int min, int max) {
// 如果所有值都已处理,或当前值不在允许范围内
if (index[0] >= nums.length || nums[index[0]] < min || nums[index[0]] > max) {
return null;
}
// 创建根节点
int rootVal = nums[index[0]];
TreeNode root = new TreeNode(rootVal);
index[0]++; // 移动到下一个值
// 递归构建左子树(值必须小于rootVal)
root.left

最低0.47元/天 解锁文章
711

被折叠的 条评论
为什么被折叠?



