欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 每日一题-重建二叉树

每日一题-重建二叉树

2025/2/2 12:52:31 来源:https://blog.csdn.net/zxjiaya/article/details/145409726  浏览:    关键词:每日一题-重建二叉树

重建二叉树

    • 题目描述
      • 示例
      • 示例 1
      • 示例 2
      • 示例 3
    • 代码实现
      • 为什么只判断前序遍历范围无效,不判断后序遍历范围有效?

题目描述

给定节点数为 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 \leq 2000 n2000
  • 节点的值 − 10000 ≤ v a l ≤ 10000 -10000 \leq val \leq 10000 10000val10000

要求:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

示例 1

在这里插入图片描述

输入:

[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

输入:

[1], [1]

返回值:

{1}

示例 3

输入:

[1,2,3,4,5,6,7], [3,2,4,1,6,5,7]

返回值:

{1,2,5,3,4,6,7}

代码实现

/*** struct TreeNode {*  int val;*  struct TreeNode *left;*  struct TreeNode *right;* };*//*** 在中序遍历数组中查找节点值的位置*/
int findIndex(int* inorder, int inorderStart, int inorderEnd, int val) {for (int i = inorderStart; i <= inorderEnd; i++) {if (val == inorder[i])return i;}return -1;
};/*** 通过前序遍历和中序遍历重建二叉树*/
struct TreeNode* buildTree(int* preorder, int preorderStart, int preorderEnd, int* inorder, int inorderStart, int inorderEnd) {// 如果前序遍历的范围无效,说明当前节点为空if (preorderStart > preorderEnd) {return NULL;}// 创建当前根节点struct TreeNode* root = (struct TreeNode*)malloc(sizeof(struct TreeNode));root->val = preorder[preorderStart];// 找到根节点在中序遍历中的位置int rootIndex = findIndex(inorder, inorderStart, inorderEnd, root->val);// 计算左子树的大小int leftTreeSize = rootIndex - inorderStart;// 构建左子树root->left = buildTree(preorder, preorderStart + 1, preorderStart + leftTreeSize, inorder, inorderStart, rootIndex - 1);// 构建右子树root->right = buildTree(preorder, preorderStart + leftTreeSize + 1, preorderEnd, inorder, rootIndex + 1, inorderEnd);return root;
};/*** 主函数,传入前序和中序遍历数组,返回根节点*/
struct TreeNode* reConstructBinaryTree(int* preOrder, int preOrderLen, int* vinOrder, int vinOrderLen ) {return buildTree(preOrder, 0, preOrderLen - 1, vinOrder, 0, vinOrderLen - 1);
}

为什么只判断前序遍历范围无效,不判断后序遍历范围有效?

  1. 前序遍历和中序遍历的范围是同步的:
    在递归过程中,前序遍历和中序遍历的范围是通过递归逻辑同步调整的。具体来说:

    • 前序遍历:根节点在前序遍历的第一个位置,左子树和右子树的范围可以通过中序遍历的结果来划分。
    • 中序遍历:根节点在中序遍历中将数组分为左子树和右子树。

    当我们确定了前序遍历的范围后,中序遍历的范围也会随之确定。因此,只要前序遍历的范围有效,中序遍历的范围必然也是有效的。

  2. 递归终止条件:
    递归终止条件是当某个子树为空时,即没有更多的节点可以处理。在递归逻辑中,我们通过以下方式确保递归终止:

    • 如果 preorderStart > preorderEnd,说明当前子树的前序遍历范围无效,这意味着当前子树为空。

    由于前序遍历和中序遍历的范围是同步调整的,当前序遍历范围无效时,中序遍历的范围也必然无效。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com