一次后序遍历即可同时获得叶子节点深度和树高:空节点返回0,叶子节点记录当前深度并返回1,非叶子节点返回左右子树高度最大值加1。

怎么用递归一次性算出每个叶子的路径深度和整棵树的分层高度
直接结论:用一次后序遍历就能同时拿到叶子节点深度和树高,关键在于递归返回值的设计——让每个节点向上汇报「以自己为根的子树高度」,同时在叶子处记录当前深度。
常见错误是分开写两遍遍历:一遍找叶子再算深度,一遍求树高。这不仅重复遍历,还容易因路径重建(比如用 vector 临时存路径)引发内存或逻辑 bug。实际只需一个 dfs 函数,参数带当前深度 depth,返回值是子树高度。
- 空节点返回高度
0 - 叶子节点(左右都为空)时,把
depth存入全局容器(如std::vector<int></int>),并返回1(自身高度) - 非叶子节点:返回
std::max(left_height, right_height) + 1,不操作叶子深度记录
为什么不能用前序遍历统计叶子深度
前序遍历(根→左→右)天然适合「向下传递深度」,但无法自然获取「该节点是否为叶子」的判断依据——你得在进入节点时就检查它是否为叶子,而此时左右子指针还没被访问,判断可靠;但问题在于:若你只靠 !node->left && !node->right 判断叶子,那没问题;可一旦树中存在空指针未初始化、或用了智能指针但 get() 返回空,就容易漏判或崩溃。
更隐蔽的坑是:前序遍历下,你无法在回溯时更新父节点高度信息,所以必须额外维护一个栈或 map 来存每层高度,徒增复杂度。而后序遍历天然支持「子树结果合并」,高度计算干净利落。
立即学习“C++免费学习笔记(深入)”;
- 务必在递归入口做空指针检查:
if (!node) return 0; - 叶子判断必须严格:
if (!node->left && !node->right),不能只判一边 - 若节点类型是
std::shared_ptr<treenode></treenode>,检查要用!node || !node->left || !node->right等价逻辑,避免解引用空指针
如何避免 vector push_back 引发的迭代器失效干扰统计
如果把所有叶子深度存进 std::vector<int></int>,后续要统计频次(比如“深度为 3 的叶子有几个”),别在遍历时边 push_back 边用 std::count 或循环遍历——这本身没问题;但若你在递归中误用 std::vector::insert 或在多线程里共享这个 vector,就可能触发重分配导致迭代器/引用失效。
安全做法是:递归只负责收集,收集完再统一处理。例如用 std::unordered_map<int int></int> 直接计数,或用 std::vector 存完后调用 std::sort 再 std::upper_bound 分段统计。
- 声明收集容器时明确作用域:局部变量最安全,避免静态或全局 vector 在多次调用间残留数据
- 若需实时统计,改用
std::map<int int> depth_count</int>,每次叶子处执行++depth_count[depth] - 不要在递归函数里对 vector 做
reserve以外的容量操作;reserve可提前设个预估值(比如树节点总数上限)
分层高度(level height)和节点深度(node depth)别混了
「分层高度」通常指从根到某层的最大节点数,即树的层数(root 算第 1 层);而「节点深度」是从根到该节点的边数(root 深度为 0)。题目里说的「分层高度计算」,大概率是指树高(height),即最大深度 + 1,或最大深度(取决于定义)。C++ 标准库没内置树高函数,必须手写。
关键区别:树高(height)是自底向上定义的(空树高为 0,非空树高 = max(左子树高, 右子树高) + 1),而深度(depth)是自顶向下累积的(根深度为 0,子节点深度 = 父深度 + 1)。两者数值常相差 1,但语义完全不同。
- LeetCode 多数题以「空节点高度为 -1」或「0」为起点,务必看题干定义;本地实现建议统一用「空节点高度为 0」
- 打印每层节点数?那是 BFS 层序遍历的事,不是 DFS 该干的——别硬在递归里塞队列
- 如果真要输出「第 k 层有多少个叶子」,必须先用 DFS 记录每个叶子的深度,再按深度分组统计,而不是试图在 DFS 中维护层编号
递归返回值的设计和空指针边界处理,比算法逻辑本身更容易出错。叶子深度收集和树高计算可以共用一套遍历,但前提是递归出口和返回逻辑完全对齐——少一个 return 或错一处 max,整棵树的高度就会偏移。
文章来自机圈观察员网,发布者:,转载请注明出处:https://www.jqgcy.com/jiquanzatan/124060.html