递归中序遍历提取bst区间[low, high]内节点值:利用bst性质剪枝,当前节点值high则跳过右子树,仅在[low, high]内时加入结果,时间复杂度o(k),k为区间内节点数。

如何用递归中序遍历提取区间内的节点值
二叉搜索树(BST)的中序遍历天然有序,所以提取 [low, high] 区间值最直接的方式是边遍历边收集。但盲目遍历整棵树效率低——必须利用 BST 左小右大的性质剪枝。
关键判断逻辑:若当前节点值 val 小于 low,说明左子树全小于 low,可跳过;若 val 大于 high,右子树全大于 high,也可跳过。
- 递归函数签名建议为:
void inorderInRange(TreeNode* root, int low, int high, vector<int>& result)</int> - 进入左子树前加判断:
if (root->val > low) inorderInRange(root->left, low, high, result); - 进入右子树前加判断:
if (root->val right, low, high, result); - 仅当
low val 时才 push 到 <code>result
迭代写法怎么避免栈溢出和重复访问
递归在极端偏斜树下可能爆栈,迭代用显式栈更可控。但注意:不能简单套用通用中序迭代模板,否则仍会访问大量无效节点。
核心优化点在于「提前压栈」和「条件弹栈」——只把可能落入区间的子树根节点压入栈,且每次弹出后按需决定是否向左右扩展。
- 初始化时只压入根节点
- 循环中弹出节点
cur后,先检查是否在区间内,再决定是否压左/右:if (cur->left && cur->val > low) stack.push(cur->left); - 右子树同理:
if (cur->right && cur->val right); - 避免把
nullptr压栈,每次压栈前判空
std::set 能否替代手写 BST 实现区间查询
可以,但要注意语义差异:std::set 底层是红黑树,支持 lower_bound 和 upper_bound,能 O(log n) 定位区间起点和终点。
不过 std::set 不提供原生的「区间内所有元素」批量提取接口,需手动迭代:
-
auto it_low = s.lower_bound(low);—— 第一个 ≥low的元素 -
auto it_high = s.upper_bound(high);—— 第一个 >high的元素 - 然后用
std::vector<int>(it_low, it_high)</int>构造结果,时间复杂度 O(k),k 是区间内元素个数 - 如果只是判断是否存在、或只需第一个匹配值,
lower_bound单次调用就够了
为什么 find + 逐个判断不是好方案
有人试图对每个 i ∈ [low, high] 调用 find(i),这是典型误区:区间长度可能远大于树中实际节点数,且 find 每次都是 O(h),总代价变成 O((high−low+1) × h),完全失去 BST 优势。
真正高效的做法永远基于树结构本身做剪枝遍历,而不是把 BST 当作无序容器去暴力枚举值域。
边界处理容易漏:比如 low 或 high 本身不在树中,但区间内有其他值——此时仍要返回所有满足 low ≤ val ≤ high 的节点,不能依赖 find 是否成功。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











