当前位置: 首页 > wzjs >正文

济南 网站定制北京官网优化公司

济南 网站定制,北京官网优化公司,网上申报系统,成人高考有用吗文章目录一、 题目描述二、 核心思路:前序找根,中序划分三、 图解算法步骤四、 一种代码实现与解析五、 关键点与复杂度分析六、与力扣106题:从中序与后序遍历序列构造二叉树的对比一、 题目描述 链接:105. 从前序与中序遍历序列…

文章目录

  • 一、 题目描述
  • 二、 核心思路:前序找根,中序划分
  • 三、 图解算法步骤
  • 四、 一种代码实现与解析
  • 五、 关键点与复杂度分析
  • 六、与力扣106题:`从中序与后序遍历序列`构造二叉树的对比

一、 题目描述

链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

给定一个二叉树的前序遍历 preorder 和中序遍历 inorder 的结果,请构建该二叉树并返回其根节点。你可以假设树中没有重复的元素。

示例:

preorder = [3, 9, 20, 15, 7]
inorder  = [9, 3, 15, 20, 7]返回的二叉树如下:3/ \9  20/  \15   7

二、 核心思路:前序找根,中序划分

解决这个问题的关键在于深刻理解前序遍历和中序遍历的特性:

  1. 前序遍历 (Preorder): [根节点, [左子树的前序遍历], [右子树的前序遍历]]

    • 特点: 序列的 第一个元素 永远是当前子树的 根节点
  2. 中序遍历 (Inorder): [[左子树的中序遍历], 根节点, [右子树的中序遍历]]

    • 特点: 根节点 总是位于序列的中间,其 左边 是所有左子树的节点,右边 是所有右子树的节点。

将这两个特性结合起来,我们的重建思路就豁然开朗了:

  1. 前序遍历 中找到根节点(就是第一个元素)。
  2. 中序遍历 中找到这个根节点的位置。
  3. 根据根节点在中序遍历中的位置,将中序遍历序列 划分 为左子树和右子树两个部分。
  4. 同时,根据左子树的节点数量,我们也能在前序遍历序列中确定左、右子树对应的子序列范围。
  5. 现在,我们拥有了左子树的前序和中序序列,以及右子树的前序和中序序列。这变成了两个规模更小的相同问题,完美契合 递归

三、 图解算法步骤

我们用示例 preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 来走一遍流程。

第一轮:

  1. 找根节点: preorder 的第一个元素是 3,所以树的根节点是 3
  2. 中序划分:inorder 中找到 3,它的索引是 1
    • inorder3 的左边是 [9],这是根节点 3 的左子树。
    • inorder3 的右边是 [15, 20, 7],这是根节点 3 的右子树。
  3. 前序划分:
    • 左子树有 1 个节点 (9)。所以在 preorder 中,根节点 3 后面的 1 个元素 [9] 对应左子树的前序遍历。
    • 右子树有 3 个节点 (15, 20, 7)。所以在 preorder 中,接下来的 3 个元素 [20, 15, 7] 对应右子树的前序遍历。

Tree Construction Step 1

递归构建左子树:

  • 问题变为:用 preorder = [9]inorder = [9] 构建树。
  • 找根节点: preorder 第一个元素是 9
  • 中序划分: inorder9 的左边和右边都为空。
  • 结论: 得到一个值为 9 的叶子节点,返回给上一层作为 3 的左孩子。

递归构建右子树:

  • 问题变为:用 preorder = [20, 15, 7]inorder = [15, 20, 7] 构建树。
  • 找根节点: preorder 第一个元素是 20
  • 中序划分:inorder 中找到 20,它的左边是 [15],右边是 [7]
  • 递归… 这个过程会继续下去,直到所有节点都构建完成。

四、 一种代码实现与解析

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode() {}*     TreeNode(int val) { this.val = val; }*     TreeNode(int val, TreeNode left, TreeNode right) {*         this.val = val;*         this.left = left;*         this.right = right;*     }* }*/
class Solution {// 使用 HashMap 存储中序遍历中 <值, 索引> 的映射,用于快速定位根节点Map<Integer, Integer> map;public TreeNode buildTree(int[] preorder, int[] inorder) {// 初始化 HashMap,空间换时间map = new HashMap<>();for (int i = 0; i < inorder.length; i++) {map.put(inorder[i], i);}// 调用递归函数,传入初始的完整数组范围// 区间定义为左闭右开 [begin, end)return build(preorder, 0, preorder.length, inorder, 0, inorder.length);}/*** 递归构建子树的核心函数* @param preorder 前序遍历数组* @param preBegin 当前处理的前序子数组的起始索引(包含)* @param preEnd   当前处理的前序子数组的结束索引(不包含)* @param inorder  中序遍历数组* @param inBegin  当前处理的中序子数组的起始索引(包含)* @param inEnd    当前处理的中序子数组的结束索引(不包含)* @return 构建好的子树的根节点*/public TreeNode build(int[] preorder, int preBegin, int preEnd, int[] inorder, int inBegin, int inEnd) {// 递归终止条件:如果子数组为空,则没有节点需要构建if (preBegin >= preEnd || inBegin >= inEnd) {return null;}// 1. 找到根节点:前序遍历的第一个元素就是根int rootVal = preorder[preBegin];TreeNode root = new TreeNode(rootVal);// 2. 在中序遍历中找到根节点的位置int rootIndex = map.get(rootVal);// 3. 计算左子树的节点数量int leftLength = rootIndex - inBegin;// 4. 递归构建左子树// 前序遍历中,左子树的范围是 [preBegin + 1, preBegin + 1 + leftLength)// 中序遍历中,左子树的范围是 [inBegin, rootIndex)root.left = build(preorder, preBegin + 1, preBegin + 1 + leftLength,inorder, inBegin, rootIndex);// 5. 递归构建右子树// 前序遍历中,右子树的范围是 [preBegin + 1 + leftLength, preEnd)// 中序遍历中,右子树的范围是 [rootIndex + 1, inEnd)root.right = build(preorder, preBegin + 1 + leftLength, preEnd,inorder, rootIndex + 1, inEnd);// 6. 返回当前构建好的根节点return root;}
}

五、 关键点与复杂度分析

  • HashMap 优化:这是本题的性能关键。如果没有 HashMap,每次在中序遍历中查找根节点都需要 O(N) 时间,导致总时间复杂度为 O(N²)。使用 HashMap 后,查找变为 O(1),总时间复杂度降为 O(N)
  • 区间定义统一采用左闭右开 [begin, end) 的区间表示法,代码会更简洁。例如,区间的长度就是 end - begin,空区间的判断就是 begin >= end
  • 时间复杂度O(N)。其中 N 是树的节点数。HashMap 的构建需要 O(N),递归 build 函数会对每个节点访问一次,每次访问中的操作(查找、计算)都是 O(1) 的。
  • 空间复杂度O(N)HashMap 占用了 O(N) 的空间。递归调用栈的深度最坏情况下(树退化成链表)也是 O(N),因此总空间复杂度为 O(N)。
    shMap的构建需要 O(N),递归build` 函数会对每个节点访问一次,每次访问中的操作(查找、计算)都是 O(1) 的。
  • 空间复杂度O(N)HashMap 占用了 O(N) 的空间。递归调用栈的深度最坏情况下(树退化成链表)也是 O(N),因此总空间复杂度为 O(N)。

六、与力扣106题:从中序与后序遍历序列构造二叉树的对比

参考:https://blog.csdn.net/lyh2004_08/article/details/149284192

特性LeetCode 105 (前序 + 中序)LeetCode 106 (后序 + 中序)
找根策略前序遍历的第一个元素 preorder[preBegin]后序遍历的最后一个元素 postorder[postEnd - 1]
划分依据统一使用中序遍历统一使用中序遍历
递归构建root -> left -> rightroot -> left -> right (或 root -> right -> left)
难点计算前序遍历中右子树的起始位置 preBegin + 1 + lenOfLeft计算后序遍历中右子树的区间 [postBegin + lenOfLeft, postEnd - 1]
http://www.dtcms.com/wzjs/124311.html

相关文章:

  • 幼教网站建设分析国家重大新闻
  • typecho 企业网站seo定义
  • 湖南省公司注册网站提升网站权重的方法
  • 单一产品做网站武汉seo外包平台
  • 网页seo优化网络
  • 上海网站科技专业做网站建设的公司
  • 苏州住房城乡建设部网站百度客服在线客服入口
  • 北京企业建站团队地推公司
  • 南宁手机企业网站定制自动seo优化
  • 前端开发用什么语言seo外包优化公司
  • 遵义市人民政府门户网站北京网络营销
  • 网站后期维护和管理怎么做今日特大新闻
  • 市网站建设公司微信推广怎么弄
  • 营销型网站外包网络营销这个专业怎么样
  • 阜阳做网站的公司360推广登录平台
  • 怎么做网站教程简单昨日凌晨北京突然宣布重大消息
  • wordpress istaxseo关键词优化软件合作
  • 企业网站的建立步骤百度官方网站下载安装
  • 政府网站建设专题培训seo技术培训机构
  • 做一个旅游团网站怎么做郑州网站建设制作公司
  • 软件开发软件开发网站seo优化排名营销
  • wordpress安装权限管理朝阳seo推广
  • 国外机械做的好的网站口碑营销什么意思
  • 几大门户网站湖南专业关键词优化
  • 做网站前端要会什么什么叫做优化
  • 山西省住房和城乡建设厅网站首页杭州网站建设公司
  • 沈阳哪家网站做的好软文广告经典案例短的
  • 怎么做网站logo怎么做好公司官网推广
  • python能否做网站百度资源搜索
  • 电子商务网站建设 上海产品如何在网上推广