题目:
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空
定义宽度为:每一层最左边非空节点和最右边非空节点之间的距离
思路
最容易想到的就是宽度优先遍历(BFS) 或者 深度优先遍历(DFS)
本文以宽度优先遍历进行阐述。
- 我们知道二叉树的根节点和孩子节点索引的关系为:假设根节点索引为
index
,那么该节点左孩子的索引就为2*index + 1
,右孩子就为2*index + 2
- 所以,每一层中的宽度都可以通过不断遍历当前层的节点位置索引–当前层最左边的非空节点位置索引+1,然后取最大值来确定每一层的最大宽度,这样就能找到整个树的最大宽度
- 我们可以定义一个辅助节点类型
helpNode
,包含三个属性:每个节点本身TreeNode
以及当前节点所在的层数depth
和当前节点的位置索引pos
- 将
helpNode
用一个队列queue
来保存,这样通过遍历二叉树中的每一个非空节点,遍历完成,最大宽度也就找到了
以下为代码+注释,看代码配合注释应该好理解一点:
// 定义TreeNode树节点
class TreeNode{
int val;
TreeNode left;
TreeNode right;
TreeNode(int val){
this.val = val;
}
}
// 额外定义一个辅助节点,存放当前节点以及节点所在层和位置
class helpNode{
TreeNode node;
int depth;
int pos;
helpNode(TreeNode node, int depth, int pos){
this.node = node;
this.depth = depth;
this.pos = pos;
}
}
//主方法
public int widthOfBinaryTree(TreeNode root) {
if(root == null)
return 0;
// 定义一个变量表示当前所在层数
int curLevel = 1;
// 定义每一层最左边的那个节点的位置索引,初始化为1
int leftOne = 1;
// 定义一个队列存放helpNode类型的节点
Queue<helpNode> queue = new LinkedList<>();
// 初始化先将根节点加入队列
queue.offer(new helpNode(root, 1, 1));
// 设置一个变量存储当前情况的最大宽度
int res = Integer.MIN_VALUE;
// 宽度优先遍历,将二叉树中的节点全部遍历一遍
while(!queue.isEmpty()){
helpNode cur = queue.poll();
// 取出当前节点所在层
int curNodeLevel = cur.depth;
// 如果当前节点所在的层数和当前正在遍历的层数不相等
// 说明已经走到下一层了,更新leftOne和curLevel
if(curNodeLevel != curLevel){
curLevel = curNodeLevel;
//因为当前现在是第一个不在遍历层的节点,它属于下一层
//并且节点是从左到右加入队列的,而且队列是先进先出
//所以我一定是下一层的第一个非空节点!
leftOne = cur.pos;
}
// 如果当前节点有左孩子或右孩子,就将其加入队列
if(cur.node.left != null)
queue.offer(new helpNode(cur.node.left, curNodeLevel + 1, 2 * cur.pos + 1));
if(cur.node.right != null)
queue.offer(new helpNode(cur.node.right, curNodeLevel + 1, 2 * cur.pos + 2));
// 将当前节点和当前层最左边的节点的距离每次都和最大值作比较进行更新
res = Math.max(res, cur.pos - leftOne + 1);
}
// 最后返回最终结果,一定是最大宽度
return res;
}
笔者也在不断学习中,如有错误,欢迎指正!