一、题目
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree)结构相同,但一些节点为空。
每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。
示例 1:
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。
二、实现
解释:
由于我们需要将给定树中的每个节点都访问一遍,我们需要遍历树。我们可以用宽度优先搜索将树遍历。
这个问题中的主要想法是给每个节点一个 position 值,如果我们走向左子树,那么 position -> position * 2,如果我们走向右子树,那么 position -> positon * 2 + 1。当我们在看同一层深度的位置值 L 和 R 的时候,宽度就是 R - L + 1。
想法和算法:
宽度优先搜索顺序遍历每个节点的过程中,我们记录节点的 position 信息,对于每一个深度,第一个遇到的节点是最左边的节点,最后一个到达的节点是最右边的节点。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int widthOfBinaryTree(TreeNode root) {
// 1.创建队列,进行层次遍历
Queue<newNode> que = new LinkedList();
// 2.根节点入队。深度0,位置0
que.add(new newNode(root,0,0));
// 3. 定义当前的深度,当前层最左侧的位置,当前最大宽度
int curDeep = 0, left=0, res=0;
// 4. 层次遍历
while(!que.isEmpty()){
// 4.1 出队节点a
newNode a = que.poll();
// 4.2 若出队节点非空,将其左右孩子入队
if(a.node != null){
que.add(new newNode(a.node.left, a.deep+1, a.pos*2)); //左孩子
que.add(new newNode(a.node.right, a.deep+1, a.pos*2+1)); //右孩子
// 4.3 判断是否遍历到下一层,更新最左侧的下标(只有遍历到下一层的第一个节点时,才会更新left)
if(curDeep != a.deep){
left = a.pos;
curDeep = a.deep;
}
// 4.4 计算当前层:从left到出队节点a 的宽度
res = Math.max(res, a.pos - left + 1);
}
}
return res;
}
}
class newNode{
TreeNode node; //当前的结点
int deep,pos; //当前节点的深度和位置(从下标0开始)
newNode(TreeNode n, int d, int p){
node = n;
deep = d;
pos = p;
}
}