662. 二叉树最大宽度
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(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:层序遍历暴力求解 首先层序遍历每一层
-
stack来保存当前行需要遍历的节点数组[root]
-
urr来表示下一层的所有节点,如果有左子树则放入curr,如果没有则放入null, 右子树同理
-
遍历如果遇到节点就正常处理左右子树,如果遇到null则放入两个null
问题: 空间复杂度太高,超出时间限制
思路2:通过记录每一个节点在当前行的下标,来优化空间复杂度
-
同样是遍历
-
改造一下stack放入的数据结构,stack[[root,0]],这是起始stack,没一个值0位代表节点,1位代表在当前行中的下标,便利的时候节点有效才放入curr,无效则不需要放入curr,pos的规律往下看
-
我们能发现当前节点的左子树在下一个行中的下标为pos * 2,右子树为pos * 2 + 1,小伙伴们画一个图就知道了,如下图
0
/ \
0 1
/ \ / \
0 1 2 3
- 最后取出curr的最后一位的下标减去第一位的下标结果+1 和max比较,取最大值
问题: 数据量大的时候,返回值为NaN,因为下标已经超出js的最大值精度了
思路3:优化下标
- 如果遍历到某一层的curr中只有一个节点的时候,那么相等于又从头开始了,即从0开始,此时重置该节点的位置信息pos为0
成功解题,完美,撒花
var widthOfBinaryTree = function (root) {
if (!root) return 0
var stack = [[root, 0]]
var curr = []
var max = 1
while (stack.length) {
var [item, pos] = stack.shift()
if (item.left) {
curr.push([item.left, pos * 2])
}
if (item.right) {
curr.push([item.right, pos * 2 + 1])
}
if (!stack.length) {
if (curr.length) {
if (curr.length === 1) { curr[0][1] = 0 }
var max = Math.max(max, curr[curr.length - 1][1] - curr[0][1] + 1)
stack = curr
curr = []
} else {
return max
}
}
}
};