zoukankan      html  css  js  c++  java
  • [leetcode]449. Serialize and Deserialize BST设计BST的编解码

    这道题学到了东西。

    /*
        一开始想着中序遍历,但是解码的时候才发现,中序遍历并不能唯一得确定二叉树。
        后来看了网上的答案,发现先序遍历是可以的,观察了一下,对于BST,先序遍历确实是可以
        唯一得确定。
        对于一般的二叉树,必须是前序和中序或者后序和中序才能唯一确定,其中中序的作用就是
        确定中心位置,以确定左右子树的前序(后序)的范围
        但是对于BST根据性质,左子树的前序序列最大的就是1st节点,所以找到序列中第一个比
        1st节点大的节点就是右子树的开始,这样就不需要中序了
    还有一种方法,保存二叉树的结构信息,这种做法可以应用于任何二叉树。保存结构信息就是空节点添加一个符号代替,解码的时候就知道结构信息了
    */ //记录数据 StringBuilder s = new StringBuilder(); // Encodes a tree to a single string. public String serialize(TreeNode root) { preTra(root); return new String(s); } //前序遍历 public void preTra(TreeNode root) { if (root==null) return; s.append(root.val); s.append(","); preTra(root.left); preTra(root.right); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if (data.length()==0) return null; String[] vals = data.split(","); return helper(vals,0,vals.length-1); } //解码过程,和由前序及中序得到二叉树的过程类似 public TreeNode helper(String[] data,int sta,int end) { if (sta > end) return null; //根据BST的特点,获得左右子树前序遍历序列的起止点 int rightSta = rSta(data,sta,end); TreeNode cur = new TreeNode(Integer.parseInt(data[sta])); cur.left = helper(data,sta+1,rightSta-1); cur.right = helper(data,rightSta,end); return cur; } public int rSta(String[] data,int sta,int end) { /* 第一个比根节点大的值就是右子树的开始 */ int a = Integer.parseInt(data[sta]); while (sta<=end) { if (Integer.parseInt(data[sta])>a) break; sta++; } return sta; }

    对于普通二叉树,前序(后序)+中序可以唯一确定二叉树,前序(后序)包含父子关系信息,中序包含兄弟关系信息

    下边是前序+中序确定二叉树

    /*
        * 如果知道(中序遍历和前序遍历)或者(中序遍历和后序遍历)可以唯一确定一棵树*/
        /*
        由前序遍历和中序遍历确定二叉树
         */
        public TreeNode PaI(int[] pre,int[] in)
        {
            if (pre.length==0) return null;
            //只剩下一个节点,就直接返回这个节点
            if (pre.length==1)
                return new TreeNode(pre[0]);
            //根据前序遍历的开头获得中序遍历的中心
            int center = pre[0];
            int c = 0;
            for (int i = 0; i < in.length; i++) {
                if (in[i]==center)
                {
                    c = i;
                    break;
                }
            }
            //根据中序遍历和中心位置确定左右子树的前中序遍历序列,递归求子树
            //左右子树的中序遍历就是中心位置的左右子序列
            //左右子树的前序遍历序列是根节点后边序列分为的两部分,长度分别与其中序遍历序列长度一样
            TreeNode cur = new TreeNode(center);
            cur.left = PaI(Arrays.copyOfRange(pre,1, 1 + c),Arrays.copyOfRange(in,0,c));
            cur.right = PaI(Arrays.copyOfRange(pre,c+1,pre.length),Arrays.copyOfRange(in,c+1,in.length));
            return cur;
        }

    步骤记住两点:所有节点信息都是从前序序列中获得(每次都是根据前序的1st节点信息作为根节点),中序遍历只是用来确定左右子树的子前序的起止点。

    然后递归获得左右子树

  • 相关阅读:
    Linux下安装启动nginx的过程
    shell编程
    Linux中的权限管理
    Linux中的模式转换
    Linux入门2
    Linux入门1
    数据库的多表查询及左右连接
    Python命令行参数sys.argv[]
    Python 读取csv文件到excel
    高级技巧
  • 原文地址:https://www.cnblogs.com/stAr-1/p/8376672.html
Copyright © 2011-2022 走看看