剑指offer——序列化,反序列化二叉树(好题)

题目描述
请实现两个函数,分别用来序列化和反序列化二叉树

思路:
序列化是指把树变成一个String,反序列化是指从String重建树,并返回树的root。

之前已经得出可以通过前序和中序遍历确定一个二叉树。


反序列化是运用了之前的思路。(重建二叉树那道题)

public class Solution {
    StringBuilder result = new StringBuilder();

    String Serialize(TreeNode root) {
        TreeNode temp = root;
        preSort(temp);
        inSort(root);
        return result.toString();
  }
    TreeNode Deserialize(String str) {
       String[] origin = str.split("#");
       int length = origin.length/2;
       int[] pre = new int[length];
       int[] in = new int[length];
       for(int i = 0; i<length; i++){
           pre[i] = Integer.valueOf(origin[i]);
           in[i] = Integer.valueOf(origin[i+length]);
       }
       TreeNode root = reConstructBinaryTree(pre, 0, pre.length - 1, in, 0, in.length - 1);
       return root;
  }
    private TreeNode reConstructBinaryTree(int[] pre, int startPre, int endPre, int[] in, int startIn, int endIn) {
        if (startPre > endPre || startIn > endIn)
            return null;
        TreeNode root = new TreeNode(pre[startPre]);
        for (int i = startIn; i <= endIn; i++)
            if (in[i] == pre[startPre]) {
                root.left = reConstructBinaryTree(pre, startPre + 1, startPre + i - startIn, in, startIn, i - 1);
                root.right = reConstructBinaryTree(pre, i - startIn + startPre + 1, endPre, in, i + 1, endIn);
            }
        return root;
    }


    void preSort(TreeNode root){
        if(root==null)
            return;
        result.append(root.val);
        result.append("#");
        preSort(root.left);
        preSort(root.right);
    }

    void inSort(TreeNode root){
         if(root==null)
            return;
        inSort(root.left);
        result.append(root.val);
        result.append("#");
        inSort(root.right);
    }
}

之前这个面试题6的思路是有条件限制的,一是不能有重复的节点(否则遍历找节点的时候就会出错了),二是只有当两个序列中所有数据都读出后才能开始反序列化。如果两个遍历序列的数据是从一个流里读出来的,那就可能需要等较长的时间。

剑指offer思路:
这里写图片描述
这里写图片描述

因为把空节点设为“#”,所以仅通过前序遍历即可反序列化,并且有相同数值的节点也不会干扰


public class Solution {
    public int index = -1;
    String Serialize(TreeNode root) {
        StringBuffer sb = new StringBuffer();
        if(root == null){
            sb.append("#,");
            return sb.toString();
        }
        sb.append(root.val + ",");
        sb.append(Serialize(root.left));
        sb.append(Serialize(root.right));
        return sb.toString();
  }
    TreeNode Deserialize(String str) {
        index++;
       int len = str.length();
        if(index >= len){
            return null;
        }
        String[] strr = str.split(",");
        TreeNode node = null;
        if(!strr[index].equals("#")){ // 因为是前序遍历的场景,所以当某个位置上的点是#时,意味着该点为null,且不存在左右结点,所以直接返回
            node = new TreeNode(Integer.valueOf(strr[index]));
            node.left = Deserialize(str);
            node.right = Deserialize(str);
        }

        return node;
  }
}
    static StringBuilder sb = null;  

    static String Serialize(TreeNode root) {  
        if (root == null)  
            return "#";  
        sb = new StringBuilder();  
        Serialize_solve(root);  
        String s = sb.toString();  
        return s.substring(0, s.length() - 1);  
    }  

    private static void Serialize_solve(TreeNode root) {  
        if (root == null) {  
            sb.append("#,");  
            return;  
        }  
        sb.append(root.val + ",");  
        Serialize_solve(root.left);  
        Serialize_solve(root.right);  
    }  

    static int index;  

    static TreeNode Deserialize(String str) {  
        if (str == null || str.trim().equals(""))  
            return null;  

        String[] strs = str.split(",");  
        index = 0;  
        return Deserialize_solve(strs);  
    }  

    private static TreeNode Deserialize_solve(String[] chars) {  
        if (chars[index].equals("#")) {  
            index++;  
            return null;  
        }  
        System.out.println(chars[index]);  
        TreeNode node = new TreeNode(Integer.parseInt(chars[index++]));  
        node.left = Deserialize_solve(chars);  
        node.right = Deserialize_solve(chars);  

        return node;  
    }  

}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值