[路飞]_二叉树最大宽度

173 阅读3分钟

leetcode-662 二叉树最大宽度
b站视频

题目介绍

给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与 满二叉树(full binary tree) 结构相同,但一些节点为空。

每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。

示例1

输入: 

           1
         /   \
        3     2
       / \     \  
      5   3     9 

输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。

示例2

输入: 

          1
         /  
        3    
       / \       
      5   3     

输出: 2
解释: 最大值出现在树的第 3 层,宽度为 2 (5,3)。

示例3

输入: 

          1
         / \
        3   2 
       /        
      5      

输出: 2
解释: 最大值出现在树的第 2 层,宽度为 2 (3,2)。

示例4

输入: 

          1
         / \
        3   2
       /     \  
      5       9 
     /         \
    6           7
输出: 8
解释: 最大值出现在树的第 4 层,宽度为 8 (6,null,null,null,null,null,null,7)。

注意:  答案在32位有符号整数的表示范围内。

解题思路

此题,我们利用完全二叉树的性质,加入从根节点开始按顺序从 1 开始编号的话,那么左节点的编号为 父节点的编号 * 2,右节点的编号为 父节点的编号 * 2 + 1

这样,我们就知道了每个节点在树中的位置,我们只需要知道每一层第一个节点的编号和最后一个节点的编号,就可以通过 最后一个节点的编号 - 第一个节点的编号 + 1 得出每一层的宽度

整棵树的最大宽度就是宽度最大的那一层的宽度

解题步骤

  1. 定义一个保存最大宽度的变量 max,定义一个数组 arr 用于存放每一层的节点
  2. 遍历数组中的节点,定义 l 用于记录每一层第一个节点的编号, r 用于记录每一层最后一个节点的编号
  3. 计算 r - l + 1 的值并与 max 值进行比较
  4. 然后将所有节点从数组中移除,将每一个节点的左右节点按顺序 push 到数组中
  5. 重复步骤 3-4 ,直到遍历完整棵树
  6. 返回 max

解题代码

var widthOfBinaryTree = function(root) {
    // 定义保存最大值max
    let max = 0n
    // 定义保存每一层的节点的数组 arr
    const arr = [{root, ind: 0n}]
    // 当数组不为空,说明还没遍历完整棵树
    while(arr.length) {
        // l 为每一层第一个节点的编号
        let l = r = arr[0].ind
        // 获取每一层的节点数量
        const len = arr.length
        for (let i = 0; i < len; i++) {
            const root = arr[0].root
            const ind = arr[0].ind
            // r 随着节点的遍历,不断指向最后一个节点
            r = ind
            // 将节点从数组中移除
            arr.shift()
            // 将该节点的左右节点插入到数组中
            root.left && arr.push({root: root.left, ind: ind * 2n})
            root.right && arr.push({root: root.right, ind: ind * 2n + 1n})
        }
        // 比较 max 值和当前层的宽度
        max = max > r - l + 1n ? max : r - l + 1n
    }
    // 返回最终结果
    return max
};

此题用 BigInt 类型进行计算是因为在计算节点编号的时候,如果数据量过大,会导致超出安全数的表示范围,导致无法计算