LeetCode 1008 Construct Binary Search Tree from Preorder Traversal (dfs)

本文解析了如何通过给定的整数先序遍历序列,利用递归策略重建二叉搜索树。重点讲解了查找插入位置的二分搜索法,并提供了Java代码示例。理解这个过程对于解决LeetCode上的相关问题至关重要。

Given an array of integers preorder, which represents the preorder traversal of a BST (i.e., binary search tree), construct the tree and return its root.

It is guaranteed that there is always possible to find a binary search tree with the given requirements for the given test cases.

binary search tree is a binary tree where for every node, any descendant of Node.left has a value strictly less than Node.val, and any descendant of Node.right has a value strictly greater than Node.val.

preorder traversal of a binary tree displays the value of the node first, then traverses Node.left, then traverses Node.right.

Example 1:

Input: preorder = [8,5,1,7,10,12]
Output: [8,5,10,1,7,null,12]

Example 2:

Input: preorder = [1,3]
Output: [1,null,3]

Constraints:

  • 1 <= preorder.length <= 100
  • 1 <= preorder[i] <= 108
  • All the values of preorder are unique.

题目链接:https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/

题目大意:根据先序遍历结果恢复二叉搜索树

题目分析:二分找到大于当前根的最小值的下标,然后再分情况二分建树

0ms,时间击败100%

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    
    private int bsearch(int[] a, int l, int r, int val) {
        int mid = 0, ans = -1;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (a[mid] > val) {
                r = mid - 1;
                ans = mid;
            } else {
                l = mid + 1;
            }
        }
        return ans;
    } 
    
    public void solve(TreeNode root, int[] preorder, int l, int r) {
        if (l > r || root == null) {
            return;
        }
        int rp = bsearch(preorder, l, r, root.val);
        root.right = rp == -1 ? null : new TreeNode(preorder[rp]);
        root.left = (rp != -1 && l >= rp) ? null : new TreeNode(preorder[l]);

        solve(root.left, preorder, l + 1, rp == -1 ? r : rp - 1);
        solve(root.right, preorder, rp + 1, r);
    }
    
    public TreeNode bstFromPreorder(int[] preorder) {
        TreeNode root = new TreeNode(preorder[0]);
        solve(root, preorder, 1, preorder.length - 1);
        return root;
    }
}

下面是你提供的 **高效版本** 的 `buildTree` 函数在 **Visual Studio 中可完整运行的 C++ 实现版本**,包含: - 完整的 `TreeNode` 定义 - 使用 `unordered_map` 加速查找根节点位置 - 使用 **Lambda 表达式递归(lambda with recursive capture)** - 主函数中构造测试用例并验证构建结果 - 前序遍历打印函数验证构造正确性 - 手动释放内存防止内存泄漏 --- ## ✅ Visual Studio 完整运行代码(C++20 要求) ```cpp #include <iostream> #include <vector> #include <unordered_map> using namespace std; // 二叉树节点定义 struct TreeNode { int val; TreeNode* left; TreeNode* right; 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) { int n = preorder.size(); unordered_map<int, int> index; for (int i = 0; i < n; ++i) { index[inorder[i]] = i; // 构建值到中序索引的映射 } // Lambda 递归函数,使用左闭右开区间 [pre_l, pre_r) 和 [in_l, in_r) function<TreeNode*(int, int, int, int)> dfs = [&](int pre_l, int pre_r, int in_l, int in_r) -> TreeNode* { if (pre_l == pre_r) { // 空子树 return nullptr; } int root_val = preorder[pre_l]; int in_root = index[root_val]; // 根节点在中序中的位置 int left_size = in_root - in_l; // 左子树大小 // 构建左右子树 TreeNode* left = dfs(pre_l + 1, pre_l + 1 + left_size, in_l, in_root); TreeNode* right = dfs(pre_l + 1 + left_size, pre_r, in_root + 1, in_r); return new TreeNode(root_val, left, right); }; return dfs(0, n, 0, n); } // 前序遍历输出函数 void preorderPrint(TreeNode* root) { if (!root) { cout << "null "; return; } cout << root->val << " "; preorderPrint(root->left); preorderPrint(root->right); } // 释放内存 void deleteTree(TreeNode* root) { if (!root) return; deleteTree(root->left); deleteTree(root->right); delete root; } }; int main() { Solution sol; // 示例输入 vector<int> preorder = {3, 9, 20, 15, 7}; vector<int> inorder = {9, 3, 15, 20, 7}; // 构建二叉树 TreeNode* root = sol.buildTree(preorder, inorder); // 打印前序遍历结果以验证是否正确 cout << "构建的二叉树前序遍历结果: "; sol.preorderPrint(root); cout << endl; // 释放内存 sol.deleteTree(root); return 0; } ``` --- ## 📌 编译与运行说明(适用于 Visual Studio) 1. 打开 **Visual Studio** 2. 创建一个 **C++ 控制台应用程序(Console Application)** 3. 替换默认代码为上述内容 4. 确保项目设置为 **C++17 或 C++20**(该代码使用了 Lambda 递归) - VS 2022 及以上支持 C++20 5. 按 `Ctrl + F5` 运行程序 --- ## 🧾 输出结果 ``` 构建的二叉树前序遍历结果: 3 9 null null 20 15 null null 7 null null ``` 表示构建成功,结构如下: ``` 3 / \ 9 20 / \ 15 7 ``` --- ## 🧠 代码解释 - 使用 `unordered_map<int, int>` 存储中序遍历中每个值对应的索引,将查找时间从 O(n) 优化到 O(1)。 - 使用 **左闭右开区间** `[l, r)` 来表示子树的前序和中序范围,避免频繁拷贝 vector。 - 使用 **Lambda 表达式递归**,C++14 起支持通过 `function` 包装 lambda 递归。 - 最终构建的树通过前序遍历验证结构是否正确。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值