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

文章目录

  • @[TOC]
  • 1.题目
  • 2.解法
    • 2.1 树的结构
    • 2.2 解法1
  • 总结

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、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

你可能感兴趣的:(数据结构与算法,java,leetcode,数据结构,算法,后端)