垂直宽度指二叉树所有节点在垂直方向(列)上的最大跨度,即最左列到最右列的列数差加1;通过为节点分配列号(根为0,左子-1、右子+1),用BFS或DFS追踪min_col与max_col计算得出,空树为0、单节点为1。

什么是垂直宽度,它和水平距离怎么对应
垂直宽度指二叉树所有节点在垂直方向(即列)上的最大跨度:最左列到最右列的列数差 + 1。关键在于给每个节点分配一个col(列号),根节点为 0,左子节点为 col - 1,右子节点为 col + 1。不是按深度或层数算,而是按投影到同一竖直线上的位置归并后统计总列数。
容易误以为“左右子树深度差”就是垂直宽度——其实完全无关。比如一根向右倾斜的链表(只有右孩子),col会一路递增到 n-1,垂直宽度就是 n;而深度可能很大,但列范围只取决于水平偏移路径。
用 BFS + 列号映射计算最左/最右列
BFS 更适合边遍历边记录列号,避免递归栈深度问题,也方便一次性拿到所有列位置。核心是维护一个队列,每个元素存 pair<treenode int></treenode>,第二个值就是该节点的 col。
- 初始化队列 push
{root, 0},同时设min_col = 0、max_col = 0 - 每 pop 一个节点,更新
min_col = min(min_col, col)、max_col = max(max_col, col) - push 左子节点时用
col - 1,右子节点用col + 1 - 循环结束后,垂直宽度 =
max_col - min_col + 1
不用哈希表存每列节点——这里只关心极值,空间 O(1) 额外变量即可。
立即学习“C++免费学习笔记(深入)”;
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
DFS 实现要注意递归参数传递方式
DFS 也能做,但必须把当前列号作为参数向下传,不能靠全局变量或静态变量——否则左右子树会互相覆盖。常见错误是写成:
int min_col = INT_MAX, max_col = INT_MIN;
void dfs(TreeNode* r, int col) {
if (!r) return;
min_col = min(min_col, col); // ❌ 全局变量导致多路径污染
max_col = max(max_col, col);
dfs(r->left, col - 1);
dfs(r->right, col + 1);
}正确做法是把极值作为引用参数传入:
void dfs(TreeNode* r, int col, int& min_col, int& max_col) {
if (!r) return;
min_col = min(min_col, col);
max_col = max(max_col, col);
dfs(r->left, col - 1, min_col, max_col);
dfs(r->right, col + 1, min_col, max_col);
}调用前要初始化 min_col = INT_MAX, max_col = INT_MIN,否则未访问节点可能导致结果异常。
空树和单节点树的边界情况
空树(root == nullptr)时垂直宽度为 0,不是 1;单节点树垂直宽度为 1 —— 这两点常被忽略,尤其测试用例含空输入时会崩。
- BFS 前先判空:
if (!root) return 0; - DFS 调用前也要同样判断,否则引用参数传入未初始化值
- 列号用
int足够(树高 ≤ 10⁴,列范围最多 ±10⁴)
真正麻烦的是极端不平衡树:10⁵ 层右斜链,BFS 队列会存 10⁵ 个节点,但列号计算本身不会溢出,只要别用 long long 过度防御反而增加开销。

















