二叉树的序列化与反序列化

二叉树的序列化与反序列化

leetCode原题链接

PS:leetCode的题多加了一点限制,就是要求不能使用全局或者静态变量存储状态。

分析:将二叉树序列化成一个字符串存储,然后将该字符串反序列化成一个二叉树。关于二叉树的操作,我们很容易的就想到了二叉树的遍历,包括层次遍历和前、中、后序遍历。因为要反序列化二叉树,所以肯定要在遍历过程中记录null节点,我们可以用一个特殊标记表示null节点.

做法1:利用前序遍历

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("#")){
        node = new TreeNode(Integer.valueOf(strr[index]));
        node.left = Deserialize(str);
        node.right = Deserialize(str);
    }

    return node;
}

做法1有几个缺点:
index是全局变量,违反了leetcode上原题的规定
因为用了递归,所以比较损耗性能。leetcode上给的测试用例比较大,所以相同的代码在牛客网上可以通过,在leetcode上就会超时。

做法2:利用层次遍历

String serialize(TreeNode root) {
    StringBuilder sb = new StringBuilder();
    Queue<TreeNode> queue = new LinkedList<TreeNode>();
    if(root != null)
        queue.add(root);
    while(!queue.isEmpty()){
        TreeNode node = queue.poll();
        if(node != null){
            queue.offer(node.left);
            queue.offer(node.right);
            sb.append(node.val + ",");
        }else{
            sb.append("#" + ",");
        }
    }
    if(sb.length() != 0)
        sb.deleteCharAt(sb.length()-1);
    return sb.toString();
}

TreeNode deserialize(String str) {
    TreeNode head = null;
    if(str == null || str.length() == 0)
        return head;
    String[] nodes = str.split(",");
    TreeNode[] treeNodes = new TreeNode[nodes.length];
    for(int i=0; i<nodes.length; i++){
        if(!nodes[i].equals("#"))
            treeNodes[i] = new TreeNode(Integer.valueOf(nodes[i]));
    }
    for(int i=0, j=1; j<treeNodes.length; i++){
        if(treeNodes[i] != null){
            treeNodes[i].left = treeNodes[j++];
            treeNodes[i].right = treeNodes[j++];
        }
    }
    return treeNodes[0];
}

很明显利用层次遍历的做法要更快一些,不用递归。

PS:利用后序遍历也可以实现,还有一种方法就是前序和中序、后序和中序都可以唯一确定一棵二叉树,所以我们在序列化的时候,可以前中和后中遍历,然后进行反序列化。

利用前序遍历和中序遍历重建二叉树,pre代表前序遍历,in代表中序遍历。

    public static TreeNode reconstruct(int[] pre, int[] in, int startpre, int endpre, 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(pre[startpre] == in[i]) {
            root.left = help(pre,in,startpre+1,startpre+i-startin,startin,i-1);
            root.right = help(pre,in,startpre+i-startin+1,endpre,i+1,endin);
        }
    }
    return root;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值