算法--二叉树最大宽度

101 阅读2分钟

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

题目

leetcode 662. 二叉树最大宽度

给你一棵二叉树的根节点 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

题解

标记法,每层从左至右依次标记,直接将 val 改为标记的序号. 每一层的层宽 = 每一层最右边节点的序号 - 每一层最左边节点的序号

var widthOfBinaryTree = function(root) {
    /** JS 存在计数溢出的问题,使用 BigInt,BigInt 不能调用 Math 中的方法。 */
    let maxWidth = 1n;
    const leftIds = []
    const dfs = (root, level, currIdx) => {
        if (leftIds[level] === undefined) {
            leftIds[level] = currIdx;
        } else {
            const width = currIdx - leftIds[level] + 1n;
            maxWidth = maxWidth > width ? maxWidth : width;
        }
        if (root.left !== null) {
            dfs(root.left, level + 1, currIdx * 2n - 1n);
        }
        if (root.right !== null) {
            dfs(root.right, level + 1, currIdx * 2n);
        }
    }
    dfs(root, 0, 1n);
    return maxWidth;    
};

代码详解

统计二叉树每层最左结点的位置和最右位置然后再计算距离即可,所谓结点所在位置按照满二叉树编号易得规律为:

  • 左孩子编号是父节点编号的两倍,即 left = 2 \times rootleft=2×root
  • 右孩子编号是父节点编号的两倍加一,即 right = 2 \times root + 1right=2×root+1

注意到树高度最大可能有 3000 层,也就是说最大编号可能达到 2^{3000}2 3000