剑指offer--<重建二叉树>

1 篇文章 0 订阅
1 篇文章 0 订阅

题目描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
题目条件:数组前序+数组中序

题目要求:重现二维数组

理论知识:二叉树,前序遍历 ,中序遍历 ,一开始忘了前序遍历和中序遍历,翻了一下数据结构,前序遍历,先处理当前节点,再处理左子树,最后处理右子树,中序遍历,先处理左子树,再处理当前节点,最后处理右子树,附:前,中,后是指的当前节点。

自己思路:
1. 前序遍历,先处理当前节点,所以,比较容易找节点,中序遍历的有个明显的特点,就是当前节点的左子树,就在当前节点的左边,所以先找根节点,通过前序遍历来确定根节点,子树根节点,中序遍历来确定,属于左子树还是右子树。
2.第一次执行程序之后,可以得到根节点,左子树和右子树,将左子树(右子树)继续当做一棵树(递归),继续执行程序,就可以确定每个节点。
3. 思考的过程中,发现确定根节点的过程类似于快速排序实现,每次递归。

具体代码(原创):

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
        //pre,in的大小始终是相同的。
        TreeNode root=null;
        if (pre.length==0)//处理空树
        {
            return root;
        }
        root=getTree(pre,in);//放入参数,进行递归处理
        return root;
    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
    private  TreeNode getTree(int[] pre, int[] in) {
        TreeNode treeNode= new TreeNode(pre[0]);//通过前序找好子树根节点
        if (pre.length==1)//处理树中只有一个根节点
        {
            treeNode.left=null;
            treeNode.right=null;
            return treeNode;
        }
        int irank=getIrank(0,pre,in);//确定数的根节点在中序的下标
        if ((irank>0)&(irank<pre.length-1))//树有左子树and右子树
        {
            int[] plow=new int[irank];//low 代表左子树部分,左子树前序列表
            int[] ilow=new int[irank];//左子树中序列表
            int[] phigh=new int[in.length-irank-1];//high 代表右子树部分,右子树前序列表
            int[] ihigh=new int[in.length-irank-1];//high 代表右子树部分,右子树中序列表
            ilow://根据子树跟节点切分中序得到左边部分
            for (int i=0;i<irank;i++ )
            {
                ilow[i]=in[i];
            }
            plow://根据子树跟节点切分前序得到左边部分
            for (int i=0;i<irank;i++ )
            {
                plow[i]=pre[i+1];
            }
            treeNode.left=getTree(plow,ilow);//左子树递归
                ihigh://根据子树跟节点切分中序得到右边部分
            for (int i=irank+1;i<in.length;i++ )
            {
                ihigh[i-irank-1]=in[i];
            }

            phigh://根据子树跟节点切分中序得到右边部分
            for (int i=irank+1;i<pre.length;i++ )
            {
                phigh[i-irank-1]=pre[i];
            }
            treeNode.right=getTree(phigh,ihigh);//you右子树递归
        }
        else if((irank>0))////树有左子树
        {
            int[] plow=new int[irank];
            int[] ilow=new int[irank];
            ilow://根据子树跟节点切分中序得到左边部分
            for (int i=0;i<irank;i++ )
            {
                ilow[i]=in[i];
            }

            plow://根据子树跟节点切分前序得到左边部分
            for (int i=0;i<irank;i++ )
            {
                plow[i]=pre[i+1];
            }
            treeNode.right=null;
            treeNode.left=getTree(plow,ilow);
        }
        else if(irank<pre.length-1)//树有右子树
        {
            //int[] plow=new int[irank];
            //int[] ilow=new int[irank];
            int[] ihigh=new int[in.length-irank-1];
            int[] phigh=new int[in.length-irank-1];

            ihigh://根据子树跟节点切分中序得到右边部分
            for (int i=irank+1;i<in.length;i++ )
            {
                ihigh[i-irank-1]=in[i];
            }

            phigh://根据子树跟节点切分中序得到右边部分
            for (int i=irank+1;i<pre.length;i++ )
            {
                phigh[i-irank-1]=pre[i];
            }
            treeNode.left=null;
            treeNode.right=getTree(phigh,ihigh);

        }
        return treeNode;
    }

    private int getIrank(int prank,int[] pre, int[] in)
    {

        for (int i=0;i<in.length;i++)
        {
            if(pre[prank]==in[i])
            {
                return i;
            }
        }
        return prank;
    }

}

再贴一下,牛客呼声比较高的代码:

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] in) 
    {
        TreeNode root=reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);//启动
        return root;    

    }
    //前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}    
    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]);//每次都是用原来的pre,而我的是每次都生成一个新的,这个更好
        for(int i=startIn;i<=endIn;i++)//还存在子树
            if(in[i]==pre[startPre])//找到根节点位置i
            {
                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;
            }
    }

代码 托管GitHub:https://github.com/johnlee2018/JZoffer.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值