【剑指offer】重建二叉树

  • 👑专栏内容:力扣刷题
  • ⛪个人主页:子夜的星的主页
  • 💕座右铭:前路未远,步履不停

目录


一、题目描述

1、题目

剑指offer:重建二叉树

给定节点数为 n 的二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建出如下图所示。

提示:

1.vin.length == pre.length

2.previn 均无重复元素

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

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

数据范围: n < = 2000 n<=2000 n<=2000,节点的值 − 1000 < = v a l < = 1000 -1000<=val<=1000 −1000<=val<=1000

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

2、示例

示例1

cpp 复制代码
输入:[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:{1,2,3,4,#,5,6,#,7,#,#,8}
说明:返回根节点,系统会输出整颗二叉树对比结果,重建结果如题面图示    

示例2

cpp 复制代码
输入:[1],[1]
返回值:{1}

示例3

cpp 复制代码
输入:[1,2,3,4,5,6,7],[3,2,4,1,6,5,7]
返回值:{1,2,5,3,4,6,7}

二、题目分析

1、递归

cpp 复制代码
public class Solution {
    public TreeNode reConstructBinaryTree(int [] pre,int [] vin) {
        int n = pre.length;
        int m = vin.length;
        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;
    }
}

2、栈

cpp 复制代码
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;
    }
}
相关推荐
mghio7 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室12 小时前
java日常开发笔记和开发问题记录
java
咖啡教室12 小时前
java练习项目记录笔记
java
鱼樱前端13 小时前
maven的基础安装和使用--mac/window版本
java·后端
RainbowSea13 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea14 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
李少兄15 小时前
Unirest:优雅的Java HTTP客户端库
java·开发语言·http
此木|西贝15 小时前
【设计模式】原型模式
java·设计模式·原型模式
可乐加.糖16 小时前
一篇关于Netty相关的梳理总结
java·后端·网络协议·netty·信息与通信