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

百度收录网站名深圳网络营销策划公司

百度收录网站名,深圳网络营销策划公司,网站建设策划案范文,做网站后有人抢注品牌关键字文章目录一、 题目回顾二、 核心思路:后序找根,中序划分三、 图解算法步骤四、 一种代码实现与深度解析五、 关键点与复杂度分析六、 总结与对比 (LC105 vs LC106)一、 题目回顾 链接:106. 从中序与后序遍历序列构造二叉树 - 力扣&#xff0…

文章目录

  • 一、 题目回顾
  • 二、 核心思路:后序找根,中序划分
  • 三、 图解算法步骤
  • 四、 一种代码实现与深度解析
  • 五、 关键点与复杂度分析
  • 六、 总结与对比 (LC105 vs LC106)

一、 题目回顾

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

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

示例:

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

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

如果你已经理解了 LC105 的“前序找根,中序划分”,那么解决这道题的思路转换就非常自然了。我们只需要把目光从前序遍历转移到后序遍历。

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

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

    • 特点: (保持不变) 根节点 划分了左、右子树。

我们的新策略是:

  1. 后序遍历 的末尾找到根节点。
  2. 中序遍历 中找到这个根节点的位置,从而划分出左、右子树。
  3. 根据左子树的节点数量,在 后序遍历 序列中确定左、右子树对应的子序列范围。
  4. 这又形成了两个规模更小的相同问题,继续 递归 解决!

三、 图解算法步骤

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

第一轮:

  1. 找根节点: postorder 的最后一个元素是 3,所以树的根节点是 3
  2. 中序划分:inorder 中找到 3
    • inorder3 的左边是 [9] (左子树)。
    • inorder3 的右边是 [15, 20, 7] (右子树)。
  3. 后序划分 (关键步骤):
    • 左子树有 1 个节点 (9)。后序遍历的顺序是“左-右-根”,所以 postorder1 个元素 [9] 对应左子树的后序遍历。
    • 右子树有 3 个节点 (15, 20, 7)。所以在 postorder 中,接在左子树后面的 3 个元素 [15, 7, 20] 对应右子树的后序遍历。

Tree Construction Step 2

递归构建左子树:

  • 问题变为:用 inorder = [9]postorder = [9] 构建树。
  • 结论: 得到一个值为 9 的叶子节点,返回。

递归构建右子树:

  • 问题变为:用 inorder = [15, 20, 7]postorder = [15, 7, 20] 构建树。
  • 找根节点: postorder 的最后一个元素是 20
  • 中序划分:inorder 中找到 20,左边是 [15],右边是 [7]
  • 后序划分: 左子树有1个节点,所以 postorder[15] 是左子树;右子树有1个节点,所以 [7] 是右子树。
  • 继续递归… 直到所有节点构建完成。

四、 一种代码实现与深度解析

/*** Definition for a binary tree node.* public class TreeNode {*     int val;*     TreeNode left;*     TreeNode right;*     TreeNode(int x) { val = x; }* }*/
class Solution {// 依然是引入 HashMap 优化,用于 O(1) 查找根节点在中序遍历中的位置Map<Integer, Integer> map;public TreeNode buildTree(int[] inorder, int[] postorder) {// 预处理中序遍历,将 <值, 索引> 存入 HashMapmap = new HashMap<>();for (int i = 0; i < inorder.length; i++) {map.put(inorder[i], i);}// 调用递归函数,初始范围为整个数组// 区间标准统一为左闭右开 [begin, end)return findNode(inorder, 0, inorder.length, postorder, 0, postorder.length);}/*** 递归构建子树的核心函数* @param inorder  中序遍历数组* @param inBegin  当前处理的中序子数组的起始索引(包含)* @param inEnd    当前处理的中序子数组的结束索引(不包含)* @param postorder 后序遍历数组* @param postBegin 当前处理的后序子数组的起始索引(包含)* @param postEnd   当前处理的后序子数组的结束索引(不包含)* @return 构建好的子树的根节点*/public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {// 基准情况: 当区间为空,无法形成节点,返回 null// 这个条件覆盖了所有递归终止的场景,无需为 size=1 的情况单独处理。if (inBegin >= inEnd || postBegin >= postEnd) {return null;}// 1. 找到根节点:后序遍历区间的最后一个元素int rootVal = postorder[postEnd - 1];TreeNode root = new TreeNode(rootVal);// 2. 在中序遍历中找到根节点的位置int rootIndex = map.get(rootVal);// 3. 计算左子树的节点数量,这是划分后序数组的关键int lenOfLeft = rootIndex - inBegin;// 4. 分治思想:递归构建左子树// 中序遍历的左子树区间: [inBegin, rootIndex)// 后序遍历的左子树区间: 从 postBegin 开始,长度为 lenOfLeft// 即 [postBegin, postBegin + lenOfLeft)root.left = findNode(inorder, inBegin, rootIndex,postorder, postBegin, postBegin + lenOfLeft);// 5. 分治思想:递归构建右子树// 中序遍历的右子树区间: [rootIndex + 1, inEnd)// 后序遍历的右子树区间: 紧跟在左子树之后,且在根节点之前// 即 [postBegin + lenOfLeft, postEnd - 1)root.right = findNode(inorder, rootIndex + 1, inEnd,postorder, postBegin + lenOfLeft, postEnd - 1);// 6. 返回当前构建好的(子)树的根节点return root;}
}

五、 关键点与复杂度分析

  • 后序数组的切分:这是本题相较于 LC105 最需要注意的地方。务必记住后序遍历是 [左, 右, 根]
    • 左子树的后序部分从 postBegin 开始,长度为 lenOfLeft
    • 右子树的后序部分从 postBegin + lenOfLeft 开始,结束于根节点之前,即 postEnd - 1
  • 递归调用顺序:在代码中,我们先递归构建 root.left,再构建 root.right。其实这个顺序可以颠倒,只要你传递给递归函数的区间参数是正确的,最终都能构建出同一棵树。这正是分治思想的魅力所在——子问题之间相互独立
  • 时间复杂度O(N)。N 是节点数。构建 HashMap 为 O(N),之后每个节点只被访问和创建一次,单次操作为 O(1)。
  • 空间复杂度O(N)HashMap 占 O(N),递归栈深度最坏情况下(链表)也为 O(N)。

六、 总结与对比 (LC105 vs LC106)

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

ft -> right(或root -> right -> left) | | **难点** | 计算前序遍历中右子树的起始位置 preBegin + 1 + lenOfLeft| 计算后序遍历中右子树的区间[postBegin + lenOfLeft, postEnd - 1]` |

这两道题关键不仅是一种递归思路和对二叉树的熟悉,更多的是一种**“分治”**思想

http://www.dtcms.com/wzjs/295007.html

相关文章:

  • 外贸网站建设如何做百度投诉中心电话
  • 网站开发制作合同站长统计入口
  • 西安网站建设罗鑫哪个浏览器不屏蔽网站
  • 东莞市做网站的优化软件
  • 即墨有做网站的吗seo搜索引擎优化费用
  • 什么网站吸引流量代运营公司可靠吗
  • 网站换空间 百度快照倒退一年多 怎么回事seo行业
  • 百度联盟做网站赚钱吗附近有学电脑培训班吗
  • 省内注销二建 建设部网站更新慢网络推广软件哪个好
  • php网站开发接口文档湖人最新排名最新排名
  • 网站推广工具有啥百度广告标识
  • wordpress超级排版器插件广告优化师是做什么的
  • 自己怎么优化网站子域名查询工具
  • 媒体平台化搜索引擎优化seo信息
  • 网站域名哪看许昌seo推广
  • 塑胶卡板东莞网站建设支持官网排名优化方案
  • 电影网站html代码广告安装接单app
  • 教育学会网站建设项目高级搜索引擎
  • 那些网站被k恢复是怎么做的短视频seo
  • 电商网站首页字体山东百度推广代理商
  • 怎么免费建设交友网站长春seo技术
  • 洛阳制作网站的公司哪家好广州竞价托管
  • 两学一做网站专题网络销售好不好做
  • 网站关键词怎么优化排名推广公司产品
  • 海南百度网站建设百度网站下载安装
  • 游戏搭建教程哪个合肥seo好
  • 永久网站四川seo技术培训
  • 青岛建设局网站关键词优化外包
  • 大学什么专业做网站百度一下百度首页登录
  • 北京网站软件制作今日新闻大事件