LeetCode 662. 二叉树最大宽度
Posted 数据结构和算法
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 662. 二叉树最大宽度相关的知识,希望对你有一定的参考价值。
截止到目前我已经写了 500多道算法题,其中部分已经整理成了pdf文档,目前总共有1000多页(并且还会不断的增加),大家可以免费下载
下载链接:https://pan.baidu.com/s/1hjwK0ZeRxYGB8lIkbKuQgQ
提取码:6666
每一行从最左边到最右边我们很容易想到的就是二叉树的BFS遍历,他就是一层一层遍历的,关于二叉树的BFS不明白的可以看下下面的视频。
所以这题思路很容易想到,就是遍历每一层的时候计算这一层最左边节点到最右边节点的距离,大致代码如下
public int widthOfBinaryTree(TreeNode root) {
if (root == null)
return 0;
//使用双端队列
Deque<TreeNode> queue = new LinkedList<>();
//把根节点加入到队列中
queue.offer(root);
//记录最大的宽度
int maxWide = 0;
while (!queue.isEmpty()) {
//当前层节点的数量
int levelCount = queue.size();
// int gap = 当前层最左边到最右边的距离
maxWide = Math.max(maxWide, gap);
//遍历当前层的所有节点,把他们的子节点在加入到队列中
for (int i = 0; i < levelCount; i++) {
TreeNode node = queue.poll();
//如果左子节点不为空,就把左子节点加入到队列中
if (node.left != null) {
queue.offer(node.left);
}
//如果右子节点不为空,就把右子节点加入到队列中
if (node.right != null) {
queue.offer(node.right);
}
}
}
return maxWide;
}
他就是从上往下一层一层遍历的,遍历每一层的时候我们需要计算当前层的最大距离,保留最大的即可。这里关键是怎么计算当前层的最大距离。
我们可以这样来计算,把它想象成为一颗满二叉树,假如根节点是遍历的第1个节点,那么他的两个子节点分别是遍历的第2个和第3个节点。并且可以推算出如果一个节点是第n个遍历的,那么他的两个子节点分别是第n*2和n*2+1个遍历的,具体我们来画个图看一下
我们可以把这些值存到一个map中,也可以把它直接存到节点中,这里我们就把他存到节点中,在遍历每一层的时候用当前层最右边的值减去最左边的值+1就是当前层的最大距离,来看下最终代码。
public int widthOfBinaryTree(TreeNode root) {
if (root == null)
return 0;
//使用双端队列
Deque<TreeNode> queue = new LinkedList<>();
//把根节点加入到队列中
queue.offer(root);
//根节点的值我们把它修改为1
root.val = 1;
//记录最大的宽度
int maxWide = 0;
while (!queue.isEmpty()) {
//当前层节点的数量
int levelCount = queue.size();
//当前层最左边节点的值
int left = queue.peekFirst().val;
//当前层最右边节点的值
int right = queue.peekLast().val;
//当前层的最大宽度就是right - left + 1,
//这里计算之后要保留最大的
maxWide = Math.max(maxWide, right - left + 1);
//遍历当前层的所有节点,把他们的子节点在加入到队列中
for (int i = 0; i < levelCount; i++) {
TreeNode node = queue.poll();
int position = node.val;
//如果左子节点不为空,就把左子节点加入到队列中
if (node.left != null) {
node.left.val = position * 2;
queue.offer(node.left);
}
//如果右子节点不为空,就把右子节点加入到队列中
if (node.right != null) {
node.right.val = position * 2 + 1;
queue.offer(node.right);
}
}
}
return maxWide;
}
这里因为左边节点先入队,所以peekFirst()返回的就是当前层最左边的节点,右边节点是最后入队的,所以peekLast()返回的是当前层最右边的节点。
//记录最大的宽度
int maxWide = 0;
public int widthOfBinaryTree(TreeNode root) {
dfs(root, 0, 1, new ArrayList<>(), new ArrayList<>());
return maxWide;
}
/**
* @param root
* @param level 遍历到第几层
* @param position 每个节点在满二叉树中的位置
* @param left 只记录最左边的节点,每层只记录一个
* @param right 只记录遍历过的最右边节点,每层只记录一个(这里是遍历过的,如果当前层有更右边的节点,
* 会把当前层的替换)
*/
public void dfs(TreeNode root, int level, int position, List<Integer> left, List<Integer> right) {
if (root == null)
return;
//首次到当前层,要把当前值分别加入到left和right中
if (left.size() == level) {
left.add(position);
right.add(position);
} else {//如果当前层已经遍历过,会替换掉
right.set(level, position);
}
//递归遍历下一层的左右子节点
dfs(root.left, level + 1, position << 1, left, right);
dfs(root.right, level + 1, position * 2 + 1, left, right);
//计算当前层的最大间距,保留最大值
maxWide = Math.max(maxWide, right.get(level) - left.get(level) + 1);
}
以上是关于LeetCode 662. 二叉树最大宽度的主要内容,如果未能解决你的问题,请参考以下文章