力扣1008:前序重建BST

力扣 1008 题解析与 C++ 代码

一、问题解析题目描述 :给定一个整数数组 preorder,表示二叉搜索树(BST)的前序遍历 结果,请重建该二叉搜索树并返回其根节点。题目保证对于给定的测试用例,总能找到一棵二叉搜索树与之对应。

核心要点:

  1. 二叉搜索树(BST)性质:对于任意节点,其左子树所有节点值 < 该节点值 < 右子树所有节点值。
  2. 前序遍历顺序:根节点 → 左子树 → 右子树。
  3. 重建思路:前序遍历的第一个元素是根节点,随后连续小于根节点的部分是左子树的前序遍历,剩余部分是右子树的前序遍历。递归应用此规则即可重建整棵树。

算法步骤:

  1. 取当前区间 [start, end] 的第一个元素作为根节点值。
  2. 找到第一个大于根节点值的索引 mid,该索引将区间划分为左子树 [start+1, mid-1] 和右子树 [mid, end]。
  3. 递归构建左子树和右子树。
  4. 返回根节点。

时间复杂度 :O(n²),最坏情况(如斜树)每次需线性扫描划分左右子树。可优化至 O(n)(见后续优化方案)。

空间复杂度:O(n),递归栈深度。

二、C++ 代码实现

基础递归解法

cpp 复制代码
/**
 * 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* bstFromPreorder(vector<int>& preorder) {
        return build(preorder, 0, preorder.size() - 1);
    }

private:
    TreeNode* build(vector<int>& preorder, int start, int end) {
        if (start > end) return nullptr;
 // 当前子树的根节点是前序遍历的第一个元素 TreeNode* root = new TreeNode(preorder[start]);
 // 找到第一个大于根节点值的索引,划分左右子树 int mid = start + 1;
        while (mid <= end && preorder[mid] < preorder[start]) {
            mid++;
        }
 // 递归构建左右子树 root->left = build(preorder, start + 1, mid1);
        root->right = build(preorder, mid, end);
        
        return root;
    }
};

优化解法(O(n) 时间复杂度)

利用单调栈模拟递归过程,一次遍历完成构建:

cpp 复制代码
class Solution {
public:
    TreeNode* bstFromPreorder(vector<int>& preorder) {
        if (preorder.empty()) return nullptr;
 stack<TreeNode*> stk;
        TreeNode* root = new TreeNode(preorder[0]);
 stk.push(root);
        
        for (int i = 1; i < preorder.size(); i++) {
            TreeNode* node = new TreeNode(preorder[i]);
            
            if (preorder[i] < stk.top()->val) {
                // 当前值小于栈顶,作为左子节点
                stk.top()->left = node;
            } else {
                // 当前值大于栈顶,找到合适的父节点 TreeNode* parent = nullptr;
                while (!stk.empty() && preorder[i] > stk.top()->val) {
                    parent = stk.top();
                    stk.pop();
                }
                parent->right = node;
            }
            
            stk.push(node);
        }
 return root;
    }
};

三、算法对比

特性 基础递归解法 优化栈解法
时间复杂度 O(n²) O(n)
空间复杂度 O(n) O(n)
核心思想 递归划分左右子树 单调栈维护节点关系
适用场景 数据量较小 数据量较大或要求高效
代码复杂度 简单直观 稍复杂但高效

四、关键点说明

  1. 边界处理 :递归解法中需确保 start > end 时返回 nullptr,避免无限递归。
  2. 划分点查找:基础解法中线性查找第一个大于根节点的索引,是 O(n²) 复杂度的根源。
  3. 单调栈原理:优化解法利用栈保存尚未设置右子树的节点,遇到更大值时弹出栈顶直到找到合适父节点,确保 BST 性质。
  4. 相关题目:本题与力扣 105(从前序与中序遍历构造二叉树)思路相似,但 BST 性质使得无需中序遍历即可确定左右子树边界。

五、测试示例

cpp 复制代码
// 测试代码示例
int main() {
    Solution solution;
    vector<int> preorder = {8, 5, 1, 7, 10, 12};
    TreeNode* root = solution.bstFromPreorder(preorder);
 // 中序遍历验证(BST 中序遍历应为升序)
    // 预期输出:1 5 7 8 10 12 return 0;
}

参考来源

相关推荐
草莓熊Lotso6 分钟前
【C++ 基于微服务的即时通讯系统】etcd + brpc 从安装到服务注册发现全链路实战
网络·数据库·c++·redis·微服务·etcd
Wang's Blog5 小时前
Java 项目实战: 交友项目:登录链路回顾与今日任务地图
java·开发语言·状态模式·交友
救救孩子把6 小时前
AI面试八股文-21_21-多模态Agent面试题-Vision-Language-Agent
人工智能·面试·职场和发展·llava·多模态agent
砚底藏山河6 小时前
python量化:行情数据回溯
java·开发语言·python·金融·maven
今年下半年6 小时前
AI智能体项目实战记录(02):初始化 Python 项目
开发语言·人工智能·python·fastapi
Williamtym6 小时前
PickGo Lab实践:用浏览器、Python和MCP串起机器人搬运仿真
开发语言·python·机器人
HPtiger6 小时前
数据结构——选择排序
数据结构·算法·排序算法
康实训6 小时前
老年评估仿真实训平台架构设计与老年人能力评估实训室教学落地实践
大数据·人工智能·算法·实训室·实训室建设
DongQiShanRen6 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CS创新实验室6 小时前
Python 对象“死“了之后去了哪?——引用计数与分代垃圾回收
开发语言·jvm·python