[深度优先遍历] 662. 二叉树最大宽度

103 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,点击查看活动详情

每日刷题 2022.08.27

题目

  • 给你一棵二叉树的根节点 root ,返回树的 最大宽度 。
  • 树的 最大宽度 是所有层中最大的 宽度 。
  • 每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。
  • 题目数据保证答案将会在  32 位 带符号整数范围内。

示例

  • 示例1

image.png

输入: root = [1,3,2,5,3,null,9]
输出: 4
解释: 最大宽度出现在树的第 3 层,宽度为 4 (5,3,null,9) 。
  • 示例2

image.png

输入:root = [1,3,2,5,null,null,9,6,null,7]
输出:7
解释:最大宽度出现在树的第 4 层,宽度为 7 (6,null,null,null,null,null,7) 。
  • 示例3

image.png

输入: root = [1,3,2,5]
输出: 2
解释: 最大宽度出现在树的第 2 层,宽度为 2 (3,2) 。

提示

  • 树中节点的数目范围是 [1, 3000]
  • -100 <= Node.val <= 100

解题思路

  • 根据题目含义:对于二叉树的每一层左节点(非空)和右节点(非空)之间的节点数(包含null节点的个数),返回所有层中的最大宽度。
  • 既然是最大宽度,那么使用层序遍历来一层一层的遍历,最后将每一层的宽度取一个最大值即可。那么还有一个问题:如果将null节点的左右子节点也记录下来呢?
  • 于是就想到了满二叉树,将所有的null节点都填充起来,对于每一层只记录左边(非空节点)和右边(非空节点)之间的差值长度。最终将每一层记录下的宽度作比较,获得最大宽度,返回即可。

AC代码

/**
 * @param {TreeNode} root
 * @return {number}
 */
var widthOfBinaryTree = function(root) {
  let obj = {
    id: 1 >>> 0,
    node: root
  }
  let queue = [obj], maxWid = 0;
  while(queue.length != 0) {
    let len = queue.length, q = [], wid = queue[0].id;
    for(let i = 0; i < len; i++) {
      // 每一层需要得出一个值
      let cur = queue[i], idx = cur.id;
      // 仅仅只需要寻找下一层可以存放的节点,并更新id
      if(cur.node.left != null) {
        let o = {
          id: (idx * 2) >>> 0,
          node: cur.node.left
        }
        q.push(o);
      }
      if(cur.node.right != null) {
        let o = {
          id: (idx * 2 + 1) >>> 0,
          node: cur.node.right
        }
        q.push(o);
      }
    }
    maxWid = Math.max(maxWid, queue[len - 1].id - wid + 1);
    queue = q;
  }
  return maxWid;
};