重建二叉树

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析

阶段4、深入jdk其余源码解析

阶段5、深入jvm源码解析

码哥源码部分

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

题目描述

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

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

做这道题之前一定要对前序遍历和中序遍历非常理解,刚开始由于我没有很好的理解他们,画图的时候一直卡着,差点以为是题目的例子错了,不过后来很好,看了朋友画的图反应过来了;

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

这道题主要是你得有node的结点意识,每个点往下层又是一个root结点;以这种思想然后进行递归,问题就很好解决了;

首先对例子进行分析:

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

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

这里面你首先根据前序遍历可知道root结点是1,然后又根据中序遍历你可以知道1左边的都是root根结点的左孩子群{4,7,2},1右边的都是root根结点的右孩子群{5,3,8,6};

根据上面我们可以画出第一个结点:

这样你可以先进入root根结点的左孩子群里面;root(1)的左孩子是2,在这里你就得把左孩子直接看成一个root根结点,其他的暂时都不用想,这样的话,以root根结点来看它的:

前序遍历序列{2,4,7}

中序遍历序列{4,7,2}

这里面你又根据前序遍历可知道root结点是2,然后根据中序遍历你可以知道2左边的都是root(2)根结点的左孩子群,2右边没有,说明没有右孩子群;

根据上面我们可以画出第二个结点:

你又进入到root(2)的左孩子群里面,以4作为根结点继续:

前序遍历序列{4,7}

中序遍历序列{4,7}

以4做为root(4)结点,根据中序遍历发现它没有左孩子只有一个右孩子,那么在这里开始遍历它的右子树,得出它俩如下的位置:

回到上一个的右子树群,一直追溯回去发现,也就只剩下是root(1)的右子树没有遍历了,然后直接又以右子树建立前序遍历和中序遍历:

前序遍历序列{3,5,6,8}

中序遍历序列{5,3,8,6}

根据前序遍历的性质,以root(3)为根结点,由中序遍历可知3左边的{5}为左孩子群,{8,6}为右孩子群;现在可以又可以确定一个结点:

以root(3)为根简单分析它的左孩子群:

前序遍历序列{3,5}

中序遍历序列{5,3}

根据中序遍历可知5是root(3)的左孩子,root(3)没有右孩子,又可以画出一个结点:

由于root(5)已经没有左孩子和右孩子了,又回到root(3)分析它的右孩子:

前序遍历序列{6,8}

中序遍历序列{8,6}

根据前序遍历root(6)为根结点,根据中序遍历root(6)左边的为左孩子群,右边的为右孩子群(很显然它没有右孩子群)

进入root(6)的左孩子群,直接得出左孩子结点为8,画出最终图像:

下面贴出代码:

    /**
     * Definition for binary tree
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    import java.util.*;
    public class Solution {
        public TreeNode reConstructBinaryTree(int [] pre,int [] in) {
            if(pre.length==0||in.length==0) {
    			return null;
    		}
    		TreeNode node=new TreeNode(pre[0]);
    		if(pre.length==1||in.length==1) {
    			return node;
    		}
    		for(int i=0;i<pre.length;i++) {
    			if(pre[0]==in[i]) {
    				node.left=reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i+1),Arrays.copyOfRange(in, 0, i));
    				node.right=reConstructBinaryTree(Arrays.copyOfRange(pre, i+1, pre.length),Arrays.copyOfRange(in, i+1, in.length));
    			}
    		}
    		return node;
        }
    }

理解上面解题的思维,程序其实并不难,只是几行代码加上两个递归;对于二叉树一定要以结点的思想去思考,这样会更容易理解.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值