首页 > 其他分享 >剑指Offer面试题7:重建二叉树

剑指Offer面试题7:重建二叉树

时间:2023-09-19 11:36:20浏览次数:43  
标签:pre 面试题 遍历 Offer 前序 vin 二叉树 节点

一、题目

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。

例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

剑指Offer面试题7:重建二叉树_中序遍历

提示:

1.vin.length == pre.length

2.pre 和 vin 均无重复元素

3.vin出现的元素均出现在 pre里

4.只需要返回根结点,系统会自动输出整颗树做答案对比

要求:空间复杂度 O(n),时间复杂度 O(n)

二、需要掌握的知识

2.1 二叉树

面试的时候提到的树,大部分是二叉树。所谓二叉树是树的一种结构,再二叉树中每个节点最多只能有两个子节点。在二叉树中最重要的莫过于遍历。通常有下面三种遍历方式。

2.2 前序遍历、中序遍历、后序遍历

前序遍历:中左右,先访问中间的根节点,再访问左子节点,再访问右子节点。上图前序遍历结果:1、2、4、7、3、5、6、8

中序遍历:左中右。先访问左子节点,再访问中间根节点,再访问右子节点。上图中序遍历结果:4、7、2、1、5、3、8、6

后序遍历:左右中。先访问左子节点,再访问右子节点,最后访问中间根节点。上图后序遍历结果:7、4、2、5、8、6、3、1

三、解决思路

对于二叉树的前序遍历,序列的第一个元素一定是根节点的值,因为序列没有重复元素,因此中序遍历中可以找到这个值,而中序遍历中根节点将二叉树分成左右子树两个部分而子树的根节点也是相应前序遍历中的首位。

具体做法

1、先根据前序遍历中的第一位建立根节点

2、然后遍历中序遍历找到这个值,这样就确定了根节点在数组中的位置

3、再按照子树的节点数将两个遍历的序列分割成子数组,将子数组送入函数建立子树

4、直到子树序列长度为0,结束递归

四、Java代码实现

4.1 递归

import java.util.*;
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
        int n = pre.length;
        int m = vin.length;
        //每个遍历都不能为0
        if(n == 0 || m == 0) 
            return null;
        //构建根节点
        TreeNode root = new TreeNode(pre[0]);
        for(int i = 0; i < vin.length; i++){
            //找到中序遍历中的前序第一个元素
            if(pre[0] == vin[i]){ 
                //构建左子树
                root.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(vin, 0, i)); 
                //构建右子树
                root.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length), Arrays.copyOfRange(vin, i + 1, vin.length));
                break;
            }
        }
        return root;
    }
}

4.2 栈

除了递归,我们也可以用类似非递归前序遍历的方式建立二叉树,利用栈辅助进行非递归,然后依次建立节点。

具体做法:

  • step 1:首先前序遍历第一个数字依然是根节点,并建立栈辅助遍历。
  • step 2:然后我们就开始判断,在前序遍历中相邻的两个数字必定是只有两种情况:要么前序后一个是前一个的左节点;要么前序后一个是前一个的右节点或者其祖先的右节点。
  • step 3:我们可以同时顺序遍历pre和vin两个序列,判断是否是左节点,如果是左节点则不断向左深入,用栈记录祖先,如果不是需要弹出栈回到相应的祖先,然后进入右子树,整个过程类似非递归前序遍历。

剑指Offer面试题7:重建二叉树_前序遍历_02

import java.util.*;
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
        int n = pre.length;
        int m = vin.length;
        //每个遍历都不能为0
        if(n == 0 || m == 0) 
            return null;
        Stack<TreeNode> s = new Stack<TreeNode>();
        //首先建立前序第一个即根节点
        TreeNode root = new TreeNode(pre[0]); 
        TreeNode cur = root;
        for(int i = 1, j = 0; i < n; i++){
            //要么旁边这个是它的左节点
            if(cur.val != vin[j]){ 
                cur.left = new TreeNode(pre[i]);
                s.push(cur);
                //要么旁边这个是它的右节点,或者祖先的右节点
                cur = cur.left; 
            }else{
                j++;
                //弹出到符合的祖先
                while(!s.isEmpty() && s.peek().val == vin[j]){
                    cur = s.pop();
                    j++;
                }
                //添加右节点
                cur.right = new TreeNode(pre[i]); 
                cur = cur.right;
            }
        }
        return root;
    }
}

标签:pre,面试题,遍历,Offer,前序,vin,二叉树,节点
From: https://blog.51cto.com/u_16244372/7523819

相关文章

  • 【面试题精讲】为什么G1收集器不需要调优性能也很优秀
    G1(Garbage-First)收集器是一种面向服务器端应用的垃圾回收器,它在JDK7u4版本中首次引入,主要用于替代CMS(ConcurrentMarkSweep)收集器。相比于其他垃圾回收器,G1收集器具有很多优点,使得它在性能和调优方面表现出色。首先,G1收集器采用了分代收集的思想,将堆内存划分为多个大小相等的区......
  • 剑指Offer面试题6:从尾到头打印链表
    一、题目输入一个链表的头节点,按链表从尾到头的顺序返回每个节点的值(用数组返回)如输入{1,2,3}的链表如下图:返回一个数组为[3,2,1]二、题解看到这题很多人第一反应是从头到尾输出会比较简单,于是我们很自然想到把链表中的节点指针反过来,改变链表结构就可以从头到尾输出了。但该方法......
  • java必背面试题
    JAVA必背面试题和项目面试通关要点一 数据库 1.常问数据库查询、修改(SQL查询包含筛选查询、聚合查询和链接查询和优化问题,手写SQL语句,例如四个球队比赛,用SQL显示所有比赛组合;举例2:选择重复项,然后去掉重复项;) 数据库里的密码如何加密(md5);(1)数据库的密码加密:单向加密,insert into......
  • 543. 二叉树的直径
    给你一棵二叉树的根节点,返回该树的直径。二叉树的直径是指树中任意两个节点之间最长路径的长度。这条路径可能经过也可能不经过根节点root。两节点之间路径的长度由它们之间边数表示。输入:root=[1,2,3,4,5]输出:3解释:3,取路径[4,2,1,3]或[5,2,1,3]的长度。......
  • 平衡二叉树的平衡机制
    1.什么是平衡二叉树,就是任意节点的左右子树的层数之差不超过1.前提它是一个二叉树。 2.一个平衡二叉树,在以下4种情况下,会破坏平衡(为啥要知道4种基本的情况,因为跟左旋和右旋的息息相关)。 2.1根节点--->左子树--->左子节点。增加节点操作。简称左左。 2.2根节点--->左子树-......
  • 剑指Offer面试题5:替换空格
    一、题目请实现一个函数,把字符串中的每个空格替换成“%20”。例如:输入“Wearehappy.",则输出”We%20are%20happy."。二、解析2.1解法一申请一个临时数组,然后再遍历这个字符串的每个字符,如果不是空格就把遍历的字符添加到临时数组中,如果是空格就添加3个符'%','2','0'分别到临时数组......
  • [剑指offer] 队列&栈篇
    JZ9 用两个栈实现队列1/*模拟入队*/2publicclassJZ9_13{4publicstaticStack<Integer>stack1=newStack<Integer>();5publicstaticStack<Integer>stack2=newStack<Integer>();67publicstaticvoidpush(intnod......
  • leetcode 二叉树的最小深度
    给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。示例1:输入:root=[3,9,20,null,null,15,7]输出:2示例2:输入:root=[2,null,3,null,4,null,5,null,6]输出:5解题思路如果当前节点为null,返......
  • leetcode 平衡二叉树
    给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。示例1:输入:root=[3,9,20,null,null,15,7]输出:true示例2:输入:root=[1,2,2,3,3,null,null,4,4]输出:false示例3:输入:root......
  • 2023 JavaScript想进 BAT 的必须要面对的面试题
    2023JavaScript面试题以及答案在本文中,您将学习面试中最常见的JavaScript面试问题和答案。在继续学习JavaScript面试问题和答案之前,我们首先学习完整的JavaScript教程。JavaScript(JS)是使用最广泛的轻量级脚本和编译编程语言,具有一流的功能,由BrendenEich于1995年开发。众所周......