3.重建二叉树

本文介绍了一种通过前序遍历和中序遍历结果重建二叉树的方法,详细解析了递归过程中的关键代码,包括如何确定根节点、左右子树的范围以及递归终止条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

 

思路:

 

如果理解了递归的访问,那么建树的过程就容易多了,前序遍历序列的第一个数(后序遍历的最后一个数)一定是根结点,所以可以根据此结点在中序序列中的位置把中序序列分为左子树和右子数两个部分,同样的道理,在左子树和右子数中同样可以用到这样的规律来确定每个中间结点。

 

自己理解:

先找到根节点,然后根据根节点在寻找根节点的左右节点,递归

 

代码:

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]);
         
        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);
                      break;
            }
                 
        return root;
    }
}

 

关键代码解析:

前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}

一、root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);

1.

弄懂这个图很关键,基本上函数里的形参看着这个图就能够写出来

2.
root.left=reConstructBinaryTree(pre,startPre+1,startPre+i-startIn,in,startIn,i-1);整个递归最难的地方在于确定左子树先序序列最右边界,也就是startPre+i-startIn这个公式怎么来的。我们知道,不管递归过程是什么样的,先序序列长度和中序序列长度一定要相同,而中序序列的边界是比较好确定的,左子树中中序序列起点是startIn,终点是i-1,左子树中先序序列起点是startPre+1,要求左子树先序序列终点,假设该终点下标为x,根据中序序列长度和先序序列长度相等的条件,得到x-(startPre+1)=i-1-startIn,求得x=i-startIn+startPre,剩下的过程就好理解了。

3.
startpre+1,指的是前序遍历左子树的开始位置,即前序遍历根节点的下一个节点。i-startin,i指的是中序遍历根节点的位置,减去中序遍历开始位置即左子树的长度。所以i-startiin+starpre是前序遍历左子树结束的位置。

4.
搞懂了:i-starin是在计算当前节点左子树节点个数;i-starin+starpre是确定当前节点左子树在pre里的位置;根据中序遍历+前序遍历的特点,pre[starpre+1]就是当前节点的左子节点,pre[i-starin+starpre+1]就是当前节点的右子节点;巧妙的是那个判定条件,越界即左右子节点不存在

 

前序遍历{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}
二、root.right=reConstructBinaryTree(pre,i-startIn+startPre+1,endPre,in,i+1,endIn);

1.

i-startIn+startPre+1解析:左子树终点:i-startIn+startPre,那么i-startIn+startPre+1就是右子书起点。

 

三、if(startPre>endPre||startIn>endIn)

    return null;

1.当startPre = endPre 时说明到了叶子节点,叶子节点的左右子树的指针为空,再往下递归,就是他这条了。个人感觉这里使用等号判断递归结束,返回当前节点更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值