1. 问题背景与核心挑战
今天遇到一道挺有意思的二叉树题目 - 力扣662题"二叉树最大宽度"。题目要求计算二叉树的最大宽度,这个宽度不是常规理解的节点数量,而是指同一层中最左和最右非空节点之间的跨度(包括中间的null节点)。这种宽度计算方式在标准BFS遍历中无法直接获取,需要我们对传统算法进行改造。
我最初尝试用普通BFS层序遍历时,发现无法准确计算包含中间null节点的宽度。比如下面这个案例:
code复制 1
/ \
3 2
/ \ \
5 3 9
用常规BFS只能得到每层节点数[1,2,3],但实际最大宽度是第3层的4(5和9之间有3个null间隔,共4个"位置")。这让我意识到需要给节点引入位置编号才能正确计算这种特殊宽度。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路与算法设计
2.1 位置编号的核心思想
关键突破点是为每个节点分配一个位置编号,模仿完全二叉树的编号方式:
- 根节点编号为0
- 左孩子编号 = 父节点编号 * 2
- 右孩子编号 = 父节点编号 * 2 + 1
这样每一层的宽度就是该层最后一个节点的编号 - 第一个节点的编号 + 1。例如:
code复制 0
/ \
1 2
/ \ / \
3 4 5 6
第三层的宽度就是6-3+1=4
2.2 带编号的BFS实现方案
基于这个思路,我们需要改造标准BFS:
- 使用队列同时存储节点和其编号
- 在遍历每一层时,记录该层首尾节点的编号差
- 维护一个全局最大宽度值
特别注意处理整层都是null的情况(虽然题目保证根节点非空),以及大数溢出问题(当树很深时编号会指数增长)。
3. 完整代码实现与解析
3.1 C++实现代码
cpp复制class Solution {
public:
int widthOfBinaryTree(TreeNode* root) {
if(!root) return 0;
queue<pair<TreeNode*, unsigned long long>> q;
q.push({root, 0});
