题目介绍
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与 满二叉树(full binary tree) 结构相同,但一些节点为空。
每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。
示例1
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。
示例2
输入:
1
/
3
/ \
5 3
输出: 2
解释: 最大值出现在树的第 3 层,宽度为 2 (5,3)。
示例3
输入:
1
/ \
3 2
/
5
输出: 2
解释: 最大值出现在树的第 2 层,宽度为 2 (3,2)。
示例4
输入:
1
/ \
3 2
/ \
5 9
/ \
6 7
输出: 8
解释: 最大值出现在树的第 4 层,宽度为 8 (6,null,null,null,null,null,null,7)。
注意: 答案在32位有符号整数的表示范围内。
解题思路
此题,我们利用完全二叉树的性质,加入从根节点开始按顺序从 1 开始编号的话,那么左节点的编号为 父节点的编号 * 2,右节点的编号为 父节点的编号 * 2 + 1
这样,我们就知道了每个节点在树中的位置,我们只需要知道每一层第一个节点的编号和最后一个节点的编号,就可以通过 最后一个节点的编号 - 第一个节点的编号 + 1 得出每一层的宽度
整棵树的最大宽度就是宽度最大的那一层的宽度
解题步骤
- 定义一个保存最大宽度的变量
max,定义一个数组arr用于存放每一层的节点 - 遍历数组中的节点,定义
l用于记录每一层第一个节点的编号,r用于记录每一层最后一个节点的编号 - 计算
r - l + 1的值并与max值进行比较 - 然后将所有节点从数组中移除,将每一个节点的左右节点按顺序
push到数组中 - 重复步骤 3-4 ,直到遍历完整棵树
- 返回
max值
解题代码
var widthOfBinaryTree = function(root) {
// 定义保存最大值max
let max = 0n
// 定义保存每一层的节点的数组 arr
const arr = [{root, ind: 0n}]
// 当数组不为空,说明还没遍历完整棵树
while(arr.length) {
// l 为每一层第一个节点的编号
let l = r = arr[0].ind
// 获取每一层的节点数量
const len = arr.length
for (let i = 0; i < len; i++) {
const root = arr[0].root
const ind = arr[0].ind
// r 随着节点的遍历,不断指向最后一个节点
r = ind
// 将节点从数组中移除
arr.shift()
// 将该节点的左右节点插入到数组中
root.left && arr.push({root: root.left, ind: ind * 2n})
root.right && arr.push({root: root.right, ind: ind * 2n + 1n})
}
// 比较 max 值和当前层的宽度
max = max > r - l + 1n ? max : r - l + 1n
}
// 返回最终结果
return max
};
此题用 BigInt 类型进行计算是因为在计算节点编号的时候,如果数据量过大,会导致超出安全数的表示范围,导致无法计算