【力扣】从前序与中序遍历序列构造二叉树

🔥博客主页: 我要成为C++领域大神

🎥系列专栏【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】

❤️感谢大家点赞👍收藏⭐评论✍️

本博客致力于分享知识,欢迎大家共同学习和交流。

10f3f804036d438784915f2c6f94fb5d.gif

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

示例 2:

输入: preorder = [-1], inorder = [-1]
输出: [-1]

分治+递归

思路

根据前序遍历的顺序可知,前序遍历得到的结果第一个元素是根节点,所以我们可以对第一个元素进行空间申请。之后找到根节点在中序遍历结果中的下标index,index左边的就是中序左子树,index右边的就是中序右子树。根据左右子树数组的长度,可以对前序遍历的数组进行划分为前序左子树前序右子树。之后递归调用构建树的函数,根节点左孩子传入前序左子树和中序左子树,根节点右孩子传入前序左子树和中序左子树。

代码实现

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left),
 * right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (preorder.empty() || inorder.empty())
            return nullptr;
        
        TreeNode* root = new TreeNode(preorder[0]);

        auto it = find(inorder.begin(), inorder.end(), preorder[0]);
        int index = distance(inorder.begin(), it);
        
        vector<int> left_inorder(inorder.begin(), inorder.begin() + index);
        vector<int> right_inorder(inorder.begin() + index + 1, inorder.end());
        vector<int> left_preorder(preorder.begin() + 1, preorder.begin() + 1 + left_inorder.size());
        vector<int> right_preorder(preorder.begin() + 1 + left_inorder.size(), preorder.end());

        root->left = buildTree(left_preorder, left_inorder);
        root->right = buildTree(right_preorder, right_inorder);

        return root;
    }
};
<think>首先,用户在问关于“中序遍历数组”的内容,包括实现方法和应用场景。我需要基于提供的引用来回答,特别是引用[4]和引用[5],因为它们直接提到了中序遍历数组。 引用[4]是关于力扣105题的,使用了先和中序遍历数组来构建二叉树。引用[5]是关于用前序遍历数组创建二叉树的C语言实现。 用户的问题焦点是“中序遍历数组”,所以我应该解释中序遍历数组是什么、如何实现中序遍历(即遍历二叉树的顺),以及它的应用场景。 关键点: - **中序遍历的定义**:在二叉树遍历中,中序遍历的顺是:左子树 → 根节点 → 右子树。所以,中序遍历数组就是这个顺访问每个节点后形成的序列。 - **实现方法**:如何从一个二叉树生成中序遍历数组?或者如何使用中序遍历数组(如引用[4]中用于构建二叉树)。 - **应用场景**: - 构建二叉树:如引用[4]所示,结合先或后序遍历数组来重建二叉树。 - 搜索二叉搜索树:在二叉搜索树中,中序遍历数组会得到一个升序列,这可用于验证BST或查找元素。 - 其他应用:如在表达式树中评估表达式,或在调试中打印树结构。 从引用中提取相关信息: - 引用[4]:展示了如何使用先和中序遍历数组构建二叉树。方法是通过递归:找到根节点(先的第一个元素),然后在inorder中找到根节点的位置,分割左子树和右子树。 - 引用[5]:提到从前序遍历数组创建二叉树,类似的概念。 - 其他引用是关于数组遍历的,但二叉树无关,所以可能不直接相关。例如,引用[3]讨论了遍历数组中的对象,但不是在二叉树上下文。 我的回答结构应该清晰: 1. **解释中序遍历数组**:定义它是什么。 2. **实现方法**: - 如何实现中序遍历递归或迭代)。 - 如何使用中序遍历数组(如构建二叉树)。 3. **应用场景**:列出常见的应用。 4. **示例**:提供一个简单的代码示例来演示实现中序遍历或使用它。 5. **生成相关问题**:作为系统指令的部分,我需要在回答末尾生成相关问题。 系统指令要求: - 使用中文回答。 - 结构清晰。 - 数学表达式用$...$或$$...$$。 - 引用末尾添加标识,如[^1]。 - 生成相关问题。 在回答中引用段落时,自然地添加引用标识。例如,提到引用[4]的内容时加[^4]。 可能的回答大纲: 1. **介绍中序遍历数组**:中序遍历二叉树遍历的一种方式,顺为左-根-右。中序遍历数组就是这个遍历结果的序列。 2. **实现方法**: - **生成中序遍历数组**:使用递归或迭代方法遍历二叉树。 - 递归方法很简单:遍历左子树,访问根,遍历右子树。 - 迭代方法使用栈。 - **使用中序遍历数组**:如构建二叉树其他遍历结合。 3. **应用场景**: - 构建二叉树(如从preorder和inorder)。 - BST验证:因为BST的中序遍历是升。 - 数据序列化。 - 引用[4]作为示例应用。 4. **代码示例**:提供一个简单的代码片段,比如在JavaScript或Python中实现中序遍历函数。 - 系统指令示例中有Python代码,所以我可以使用JavaScript或Python。 - 引用[4]是Java代码;引用[5]是C语言。我可以简化或适配。 5. **生成相关问题**:结束时添加相关问题。 相关问题想法: 1. 如何用递归实现中序遍历? 2. 中序遍历在二叉搜索树中有何特殊用途? 3. 如何从先和中序遍历数组重建二叉树? 确保回答真实可靠:基于标准计算机科学知识。 最终回答结构: - 开头解释。 - 实现部分。 - 应用场景。 - 代码示例。 - 相关问题。 </think>### 中序遍历数组的实现及应用 中序遍历二叉树遍历的一种方式,其顺为:**左子树 → 根节点 → 右子树**。中序遍历数组是指通过这种遍历方式生成的节点值序列(通常是整数或其他数据类型)。这种遍历在二叉树操作中非常基础,常用于构建树结构、验证二叉搜索树(BST)或序列化数据。下面我将逐步解释其实现方法、应用场景,并提供代码示例。 #### 1. **中序遍历数组的实现方法** 实现中序遍历数组的核心是通过递归或迭代算法遍历二叉树,并将节点值按顺存入数组中。以下是常见的实现方式: - **递归方法**: 这是最简单的方法。算法思路是: 1. 递归遍历左子树。 2. 访问根节点,将其值添加到数组。 3. 递归遍历右子树。 时间复杂度为 $O(n)$($n$ 是节点数),空间复杂度为 $O(h)$($h$ 是树高,主要由递归栈占用)。 - **迭代方法**: 使用栈数据结构模拟递归过程: 1. 从根节点开始,将所有左子节点入栈。 2. 弹出栈顶节点,访问该节点并将其值添加到数组。 3. 处理该节点的右子树。 迭代法避免了递归栈溢出的风险,更适合大型树结构,时间和空间复杂度递归类似[^4]。 中序遍历数组的性质: - 对于二叉搜索树(BST),中序遍历数组总是 **升**(因为 BST 的定义确保左节点 < 根节点 < 右节点)。 - 在一般二叉树中,中序遍历数组反映了树的“左-根-右”结构,可用于重建树的逻辑关系。 #### 2. **应用场景** 中序遍历数组在多个领域有重要应用: - **二叉树重建**:结合其他遍历序列(如先或后),可以唯一重建二叉树。例如,给定先序遍历数组(根-左-右)和中序遍历数组,通过递归分割子树,能高效还原树结构(如引用[4]中的力扣105题所示)。这是因为中序遍历数组提供了根节点的位置信息,从而区分左右子树[^4][^5]。 - **二叉搜索树(BST)操作**: - **验证 BST**:如果中序遍历数组是升序列,则该树是 BST。 - **查找第 k 小元素**:直接访问中序遍历数组的第 k 个元素即得结果(时间复杂度 $O(1)$ 如果数组已生成)。 - **数据序列化**:将二叉树转换为中序遍历数组,便于存储或传输;反序列化时再结合其他数据重建树。 - **表达式评估**:在表达式树(如算术表达式)中,中序遍历数组可直接生成中缀表达式(例如 $(a + b) * c$)[^4]。 - **调试分析**:打印中序遍历数组可直观检查二叉树结构,用于算法测试或性能优化。 #### 3. **代码示例** 以下是一个使用 JavaScript 实现中序遍历数组的递归方法示例。该函数接受二叉树根节点,并返回中序遍历数组: ```javascript class TreeNode { constructor(val) { this.val = val; this.left = this.right = null; } } // 递归实现中序遍历数组 function inorderTraversal(root) { const result = []; // 存储遍历结果的数组 // 定义递归辅助函数 function traverse(node) { if (node === null) return; // 基线条件:节点为空则返回 traverse(node.left); // 递归左子树 result.push(node.val); // 访问根节点,添加到数组 traverse(node.right); // 递归右子树 } traverse(root); // 从根节点开始遍历 return result; } // 示例用法 const root = new TreeNode(1); root.left = new TreeNode(2); root.right = new TreeNode(3); console.log(inorderTraversal(root)); // 输出: [2, 1, 3] (表示左节点2 → 根1 → 右节点3) ``` 在这个示例中: - `TreeNode` 类定义了二叉树节点。 - `inorderTraversal` 函数递归遍历树并构建中序遍历数组。 - 输出 `[2, 1, 3]` 符合中序遍历(左子树值在前)。 对于迭代方法或其他语言实现(如引用[4]中的 Java 或 C),逻辑类似,但需手动管理栈[^4][^5]。 #### 总结 中序遍历数组是二叉树操作的基础工具,实现简单(递归或迭代),应用广泛,尤其在树重建和 BST 处理中。通过结合其他遍历序列(如先),它能唯一确定二叉树结构,适用于算法竞赛(如 LeetCode)和实际开发场景。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值