[剑指OFFER]之树:JZ37 序列化二叉树

1.题目

请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。

二叉树的序列化(Serialize)是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树等遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#)

二叉树的反序列化(Deserialize)是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

2.解法

2.1 树的结构

public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;
    public TreeNode(int val) {
        this.val = val;
    }
}

要求实现的方法

public class Solution {
    String Serialize(TreeNode root) {
        
    }
    TreeNode Deserialize(String str) {
       
    }
}

2.2 解法1

通过中序遍历 加 前序(或者后续) 即可恢复一颗二叉树。
先定义遍历

    private StringBuilder preOrder(TreeNode root) {
        if (root == null) return null;
        StringBuilder prevs = new StringBuilder();
        prevs.append(root.val);
        StringBuilder left = preOrder(root.left);
        StringBuilder right = preOrder(root.right);
        if (left!=null) prevs.append(","+left);
        if (right != null) prevs.append(","+right);
        return prevs;
    }

    private StringBuilder inOrder(TreeNode root) {
        if (root == null) return null;
        StringBuilder left = inOrder(root.left);
        if (left == null) left = new StringBuilder();
        if(left.length()==0) left.append(root.val);
        else  left.append(","+root.val);
        StringBuilder right = inOrder(root.right);
        if (right != null)
            left.append(","+right);
        return left;
    }

序列化用遍历,然后将两个序列化结果用分号分割后连起来。

    String Serialize(TreeNode root) {
        StringBuilder preOrder = preOrder(root);
        StringBuilder inOrder = inOrder(root);
        StringBuilder stringBuilder = new StringBuilder();
        if(preOrder!=null) stringBuilder.append(preOrder);
        stringBuilder.append(";");
        if(inOrder!=null) stringBuilder.append(inOrder);
        return stringBuilder.toString();
    }

反序列化时,使用reConstructBinaryTree(int[] pre, int[] vin)将数组迭代取出根及左右子树即可。

    TreeNode Deserialize(String str) {
        String[] orders = str.split(";");
        if (orders == null || orders.length == 0) return null;
        int size = orders[0].split(",").length;

        int[] pre = new int[size];
        int[] vin = new int[size];
        int i = 0;
        for (String s : orders[0].split(",")) {
            if (s.equals("")) continue;
            pre[i++] = Integer.parseInt(s);
        }
        i = 0;
        for (String s : orders[1].split(",")) {
            if (s.equals("")) continue;
            vin[i++] = Integer.parseInt(s);
        }
        return reConstructBinaryTree(pre, vin);
    }

    private TreeNode reConstructBinaryTree(int[] pre, int[] vin) {
        if (pre == null || pre.length == 0) return null;
        int rootval = pre[0];

        //查出中序遍历根节点的位置
        int pos = -1;
        for (int i = 0; i < vin.length; i++) {
            if (vin[i] == rootval) {
                pos = i;
                break;
            }
        }

        int left_len = pos;
        int right_len = pre.length - 1 - pos;

        int[] pre_left = new int[left_len];
        int[] pre_right = new int[right_len];
        int[] vin_left = new int[left_len];
        int[] vin_right = new int[right_len];

        System.arraycopy(pre, 1, pre_left, 0, left_len);
        System.arraycopy(pre, 1 + left_len, pre_right, 0, right_len);
        System.arraycopy(vin, 0, vin_left, 0, left_len);
        System.arraycopy(vin, 1 + left_len, vin_right, 0, right_len);

        TreeNode node = new TreeNode(rootval);
        node.left = reConstructBinaryTree(pre_left, vin_left);
        node.right = reConstructBinaryTree(pre_right, vin_right);
        return node;
    }

总结

通过中序遍历 加 前序(或者后续) 即可恢复一颗二叉树。

算法系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/alg
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
二叉树序列化和反序列化将一个二叉树转换成字符串表示,或者将字符串表示转换成二叉树,实现二叉树的存储和传输。以下是实现方法: 1. 序列化 二叉树序列化可以使用前序遍历或者层次遍历。这里以前序遍历为例,具体步骤如下: 1. 如果节点为空,使用特殊字符(如“#”)表示,将其添加到序列化字符串中; 2. 如果节点不为空,将其值添加到序列化字符串中,并递归处理其左右子节点。 示例代码如下: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right class Codec: def serialize(self, root: TreeNode) -> str: if not root: return "#" return str(root.val) + "," + self.serialize(root.left) + "," + self.serialize(root.right) def deserialize(self, data: str) -> TreeNode: def buildTree(iter): val = next(iter) if val == "#": return None node = TreeNode(int(val)) node.left = buildTree(iter) node.right = buildTree(iter) return node iter = iter(data.split(",")) return buildTree(iter) ``` 2. 反序列化 二叉树的反序列化需要根据序列化字符串递归地构建二叉树。具体步骤如下: 1. 如果当前字符为特殊字符(如“#”),返回空节点; 2. 如果当前字符不是特殊字符,创建一个节点,并设置其值为当前字符; 3. 递归处理左子节点和右子节点。 示例代码如下: ```python class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right class Codec: def serialize(self, root: TreeNode) -> str: if not root: return "#" return str(root.val) + "," + self.serialize(root.left) + "," + self.serialize(root.right) def deserialize(self, data: str) -> TreeNode: def buildTree(iter): val = next(iter) if val == "#": return None node = TreeNode(int(val)) node.left = buildTree(iter) node.right = buildTree(iter) return node iter = iter(data.split(",")) return buildTree(iter) ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟空学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值