【问题描述】[中等]

根据一棵树的前序遍历与中序遍历构造二叉树。注意:
你可以假设树中没有重复的元素。例如,给出前序遍历 preorder = [3,9,20,15,7]
中序遍历 inorder = [9,3,15,20,7]
返回如下的二叉树:3/ \9  20/  \15   7

【解答思路】

1. 递归

先序遍历的顺序是根节点,左子树,右子树。中序遍历的顺序是左子树,根节点,右子树。
只需要根据先序遍历得到根节点,然后在中序遍历中找到根节点的位置,它的左边就是左子树的节点,右边就是右子树的节点。

时间复杂度:O(N) 空间复杂度:O(N)

public TreeNode buildTree(int[] preorder, int[] inorder) {return buildTreeHelper(preorder, 0, preorder.length, inorder, 0, inorder.length);
}private TreeNode buildTreeHelper(int[] preorder, int p_start, int p_end, int[] inorder, int i_start, int i_end) {// preorder 为空,直接返回 nullif (p_start == p_end) {return null;}int root_val = preorder[p_start];TreeNode root = new TreeNode(root_val);//在中序遍历中找到根节点的位置int i_root_index = 0;for (int i = i_start; i < i_end; i++) {if (root_val == inorder[i]) {i_root_index = i;break;}}int leftNum = i_root_index - i_start;//递归的构造左子树root.left = buildTreeHelper(preorder, p_start + 1, p_start + leftNum + 1, inorder, i_start, i_root_index);//递归的构造右子树root.right = buildTreeHelper(preorder, p_start + leftNum + 1, p_end, inorder, i_root_index + 1, i_end);return root;
}

HashMap优化

public TreeNode buildTree(int[] preorder, int[] inorder) {HashMap<Integer, Integer> map = new HashMap<>();for (int i = 0; i < inorder.length; i++) {map.put(inorder[i], i);}return buildTreeHelper(preorder, 0, preorder.length, inorder, 0, inorder.length, map);
}private TreeNode buildTreeHelper(int[] preorder, int p_start, int p_end, int[] inorder, int i_start, int i_end,HashMap<Integer, Integer> map) {if (p_start == p_end) {return null;}int root_val = preorder[p_start];TreeNode root = new TreeNode(root_val);int i_root_index = map.get(root_val);int leftNum = i_root_index - i_start;root.left = buildTreeHelper(preorder, p_start + 1, p_start + leftNum + 1, inorder, i_start, i_root_index, map);root.right = buildTreeHelper(preorder, p_start + leftNum + 1, p_end, inorder, i_root_index + 1, i_end, map);return root;
}
2. 迭代 栈

用一个栈保存已经遍历过的节点,遍历前序遍历的数组,一直作为当前根节点的左子树,直到当前节点和中序遍历的数组的节点相等了,那么我们正序遍历中序遍历的数组,倒着遍历已经遍历过的根节点(用栈的 pop 实现),找到最后一次相等的位置,把它作为该节点的右子树。

代码细节

  • 用一个栈保存已经遍历的节点
  • 用 curRoot 保存当前正在遍历的节点


    时间复杂度:O(N) 空间复杂度:O(N)
public TreeNode buildTree(int[] preorder, int[] inorder) {if (preorder.length == 0) {return null;}Stack<TreeNode> roots = new Stack<TreeNode>();int pre = 0;int in = 0;//先序遍历第一个值作为根节点TreeNode curRoot = new TreeNode(preorder[pre]);TreeNode root = curRoot;roots.push(curRoot);pre++;//遍历前序遍历的数组while (pre < preorder.length) {//出现了当前节点的值和中序遍历数组的值相等,寻找是谁的右子树if (curRoot.val == inorder[in]) {//每次进行出栈,实现倒着遍历while (!roots.isEmpty() && roots.peek().val == inorder[in]) {curRoot = roots.peek();roots.pop();in++;}//设为当前的右孩子curRoot.right = new TreeNode(preorder[pre]);//更新 curRootcurRoot = curRoot.right;roots.push(curRoot);pre++;} else {//否则的话就一直作为左子树curRoot.left = new TreeNode(preorder[pre]);curRoot = curRoot.left;roots.push(curRoot);pre++;}}return root;
}
class Solution {public TreeNode buildTree(int[] preorder, int[] inorder) {if(preorder.length==0 || inorder.length==0) {return null;}//根据前序数组的第一个元素,就可以确定根节点TreeNode root = new TreeNode(preorder[0]);for(int i=0;i<preorder.length;++i) {//用preorder[0]去中序数组中查找对应的元素if(preorder[0]==inorder[i]) {//将前序数组分成左右两半,再将中序数组分成左右两半//之后递归的处理前序数组的左边部分和中序数组的左边部分//递归处理前序数组右边部分和中序数组右边部分int[] pre_left = Arrays.copyOfRange(preorder,1,i+1);int[] pre_right = Arrays.copyOfRange(preorder,i+1,preorder.length);int[] in_left = Arrays.copyOfRange(inorder,0,i);int[] in_right = Arrays.copyOfRange(inorder,i+1,inorder.length);root.left = buildTree(pre_left,in_left);root.right = buildTree(pre_right,in_right);break;}}return root;}
}作者:wang_ni_ma
链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/dong-hua-yan-shi-105-cong-qian-xu-yu-zhong-xu-bian/

【总结】

1.前中后序遍历变化的是[中]的位置,左到右的顺序不改变
  • 前序遍历 中左右
  • 中序遍历 左中右
  • 后续遍历 左右中
2.还原二叉树 借助HashMap or copyOfRange

根据前序和后序遍历构造二叉树
[Leetcode][第889题][JAVA][根据前序和后序遍历构造二叉树][分治][递归]
前序+中序遍历可画出原二叉树
[Leedcode][JAVA][第105题][从前序与中序遍历序列构造二叉树][栈][递归][二叉树]
后续+中序遍历可画出原二叉树
[Leetcode][第106题][JAVA][ 从中序与后序遍历序列构造二叉树][分治][递归]

3. 多画图 写写写 遍历代码 手撕变量 大脑保持清醒

转载链接:https://leetcode-cn.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-by–22/

[Leedcode][JAVA][第105题][从前序与中序遍历序列构造二叉树][栈][递归][二叉树]相关推荐

  1. 二叉树 中序遍历 python_LeetCode 105 树 从前序与中序遍历序列构造二叉树(Medium)

    17(105) 从前序与中序遍历序列构造二叉树(Medium) 描述 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 示例 例如,给出前序遍历 preorder = ...

  2. LeetCode 刷题之旅(2020.05.22)——105. 从前序与中序遍历序列构造二叉树(中)

    LeetCode 刷题之旅(2020.05.22)--105. 从前序与中序遍历序列构造二叉树(中) 题目: 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如, ...

  3. 刷题记录8---验证二叉搜索树+二叉树的层序遍历+从前序与中序遍历序列构造二叉树+二叉树展开为链表+二叉树的最近公共祖先

    前言 所有题目均来自力扣题库中的hot 100,之所以要记录在这里,只是方便后续复习 98.验证二叉搜索树 题目: 给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树. 有效 二叉搜 ...

  4. 【LeetCode】【HOT】105. 从前序与中序遍历序列构造二叉树(哈希表+递归)

    [LeetCode][HOT]105. 从前序与中序遍历序列构造二叉树 文章目录 [LeetCode][HOT]105. 从前序与中序遍历序列构造二叉树 package hot;import java ...

  5. 【必拿下系列】106. 从中序与后序遍历序列构造二叉树105从前序与中序遍历序列构造二叉树

    两题各自的链接放这里了: 链接: 106 链接: 105 106.从中序与后序遍历序列构造二叉树 如果你是不知道理论的,那就得仔细分析了, 举个例子: 输入:inorder = [9,3,15,20, ...

  6. 105从前序与中序遍历序列构造二叉树 106 从中序与后序遍历序列构造二叉树 (递归 + 哈希)

    引言 这两道题主要是考察二叉树遍历的掌握,即由前序和中序推出原二叉树,由后序和中序推出原二叉树,这里先来说一下推导过程: 前序和中序 知道前序遍历和中序遍历,如何推原二叉树?(直接是结论,可以自行推导 ...

  7. 二叉树 中序遍历 python_leetcode No.105 从前序与中序遍历序列构造二叉树

    题目链接: 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)​leetcode-cn.com 题目描述: 根据一棵树的前序遍历与中序遍历构造二叉树,可以假设树中没有重复的元素. 示例: 前 ...

  8. 【LeetCode系列】从中序与后序遍历序列构造二叉树 从前序与中序遍历序列构造二叉树...

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 105. 从前序与中序遍历序列构造二叉树 根据一棵树的前序遍历与中序遍历构造二叉树 ...

  9. 找树左下角的值+路径总和+从前序和中序遍历序列构造二叉树(day18*)

    这篇可以主要关注一下如何确定递归时是否需要返回值. LC513. 找树左下角的值 给定一个二叉树的根节点,请找出该二叉树的 最底层最左边 节点的值. 思路1 层序遍历 class Solution:d ...

最新文章

  1. 查询linux kafka安装目录,Linux下安装并(单节点)配置启动Kafka
  2. python解析库beautifulsoup_12_Python_解析库_BeautifulSoup的使用
  3. Grub2倒计时失效
  4. 一款java代码生成器(我受够了加班),走起!
  5. 传递对象_洮北区司法局矫正对象献爱心传递社会正能量
  6. android反射开启通知_Android中反射的简单应用
  7. C语言重点难点:与,或和异或
  8. 重磅推荐,计算机视觉开源周报20191003期
  9. mysql 交换空间_MySQL优化纪录
  10. 纽约人寿CEO加入NYDIG董事会
  11. Fresher玩深沉
  12. python的help()
  13. java如何画五角星_Java——绘制五角星
  14. svg图形计算、矩阵函数计算、图形点位绝对坐标计算
  15. 使用easyrsa来制作证书
  16. SVN出现红绿双向箭头原因
  17. 26、灭火系统中最不利点处洒水喷头的工作压力是多少
  18. usb驱动的基本结构和函数简介【转】
  19. 基于python计算包含贝塞尔函数的积分
  20. 测试开发面试题(1)

热门文章

  1. 【计算机视觉】基于OpenCV的人脸识别
  2. OpenGL学习之路(二)
  3. Arcengine 基本操作(待更新)
  4. 几种常用的数字滤波器
  5. 各种推荐资料汇总。。。
  6. Linux 常用测试命令
  7. GridView强制不换行
  8. Promise解决多个异步Ajax请求导致的代码嵌套问题(完美解决方案)
  9. Mybatis源码学习笔记
  10. mpvue 从零开始 女友的衣装 1 pages