如何计算二叉树的最大宽度?

272 阅读3分钟

前言

本文将介绍如何计算二叉树的最大宽度,也就是一棵二叉树中最宽的那一层有多少个节点。

正文

给出一棵二叉树,计算这棵二叉树的最大宽度,最大宽度指的是二叉树中节点数最多的那一层。

例如,下图二叉树中,第3层的节点数最多,第3层有4个节点,所以这棵二叉树的最大宽度为4

思路解析

看到这个题时,第一反应就是把每一层的节点数都计算一遍,看哪个最大就好了,第二反应就是,不一定是越往下节点数就越多,如上图中的第4层只有1个节点,而第3层有4个节点。

根据我们的两个反应来看下如何分析这道题,首先想到的是按层遍历,之前介绍过如何按层遍历二叉树,跟这个题目有点关系,在按层遍历的基础上计算出每一层的节点即可。

下面就来看下如何实现每层的节点数统计,我们知道二叉树按层遍历是使用队列来实现的,统计每层的节点数也是借助队列来实现,不过要额外增加几个变量,这几个变量的作用就是用来标记每一层的遍历是否结束。

以上图二叉树为例,具体步骤如下:

  • 增加变量:当前层结束变量curEnd、下一层结束变量nextEnd、二叉树的最大宽度max、当前操作节点cur
  • 设置curEnd节点5节点5进入队列,也就是节点入队之前标记curEnd
  • 节点5从队列里弹出,当前层节点数+1
  • 节点3进入队列,nextEnd标记为节点3
  • 节点7进入队列,nextEnd标记为节点7
  • 当前操作节点cur是否为curEnd,如果是那么本层遍历结束,节点5curEnd,第1层遍历结束,节点数为1
  • 1层结束后,对比计算的节点数和max的值大小,如果大于max则更新max的值。
  • nextEnd的值赋值给curEnd,即第一层结束后,curEnd值为节点7,准备下一层的遍历和计算。
  • 节点3弹出,当前层节点数加1,此时第2层节点数为1
  • 节点1进入队列,nextEnd标记为节点1
  • 节点6进入队列,nextEnd标记为节点6
  • 节点7弹出,当前层节点数加1,此时第2层节点数为2
  • 节点6进入队列,nextEnd标记为节点6
  • 节点9进入队列,nextEnd标记为节点9
  • 节点7curEnd,如果是那么本层遍历结束,第2层遍历结束,节点数为2,将max更新为2
  • 依次类推,遍历每一层的节点,计算对应的节点个数。

代码实现

根据上面的分析,我们来看下代码实现,代码如下:

public int maxWidth(Node head) {
   if (head == null) {
      return 0;
   }
   Queue<Node> queue = new LinkedList<>();
   queue.add(head);
   // 当前层,最右节点是谁
   Node curEnd = head; 
   // 下一层,最右节点是谁
   Node nextEnd = null; 
   int max = 0;
   // 当前层的节点数
   int curLevelNodes = 0; 
   while (!queue.isEmpty()) {
      Node cur = queue.poll();
      if (cur.left != null) {
         queue.add(cur.left);
         nextEnd = cur.left;
      }
      if (cur.right != null) {
         queue.add(cur.right);
         nextEnd = cur.right;
      }
      curLevelNodes++;
      if (cur == curEnd) {
         max = Math.max(max, curLevelNodes);
         curLevelNodes = 0;
         curEnd = nextEnd;
      }
   }
   return max;
}

总结

本文介绍了如何计算二叉树的最大宽度,也就是一棵二叉树中最宽的那一层有多少个节点,文中使用有限几个变量在按层遍历的基础上实现了每层的节点数统计,另外也可以使用Map来作为辅助实现统计功能,使用Map的话相对于本文中的解法就比较简单了,这里就不再展开介绍了。