leetcode-二叉树最大宽度

161 阅读2分钟

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

题目描述

给你一棵二叉树的根节点 root ,返回树的 最大宽度 。

树的 最大宽度 是所有层中最大的 宽度 。

每一层的 宽度 被定义为该层最左和最右的非空节点(即,两个端点)之间的长度。将这个二叉树视作与满二叉树结构相同,两端点间会出现一些延伸到这一层的 null 节点,这些 null 节点也计入长度。

题目数据保证答案将会在  32 位 带符号整数范围内。

 

示例 1:

662示例1.jpg

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

示例 2:

662示例2.jpg

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

示例 3:

662示例3.jpg

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

提示:

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

思路

本题题意有点难理解,反正我是看了3个示例后才看懂的。就是要求每层左右节点的编码的差值,中间的null节点也是占用编码的。整体思路不难,给每个节点1个编号,假设父节点的编码是k,那么左子节点的编码就是k*2,右子节点的编号就是k*2+1。我们可以使用层序遍历的方式,求出每1层的最左编号和最优编号,然后就可以得到这1层的宽度,遍历每一层的宽度,取最大值即可。
题目至此都没什么难度,但是已提交就失败的,看到了这组比较奇葩的数据,太长不粘贴了,大概就是左子节点都是空,每层都只有最右子节点,想了一下,我们上面编号的方式就很有可能超限了。1种优化的方法是,对每1层,初始编号后,得到第一个节点的编码,将这个编号强制编号成0,即减去一个公共的reIndexMinus值,这层所有的节点都减去相同的值,那么这个差值还是会保持不变,这样就能过掉这组数据。

Java版本代码

class Solution {
    public int widthOfBinaryTree(TreeNode root) {
        int ans = 0;
        Queue<TreeNode662> queue = new ArrayDeque<>();
        queue.add(new TreeNode662(root, 0));
        while (!queue.isEmpty()) {
            int size = queue.size();
            int left = -1, right = -1;
            // 重编号需要减去的值
            int reIndexMinus = queue.peek().index;
            while (size-- > 0) {
                TreeNode662 treeNode662 = queue.poll();
                treeNode662.index = treeNode662.index - reIndexMinus;
                if (left < 0) {
                    left = treeNode662.index;
                    right = left;
                } else {
                    right = treeNode662.index;
                }
                if (treeNode662.node.left != null) {
                    queue.offer(new TreeNode662(treeNode662.node.left, treeNode662.index * 2));
                }
                if (treeNode662.node.right != null) {
                    queue.offer(new TreeNode662(treeNode662.node.right, treeNode662.index * 2 + 1));
                }
            }
            ans = Integer.max(ans, right - left + 1);
        }
        return ans;
    }

    class TreeNode662 {
        TreeNode node;
        int index;

        public TreeNode662(TreeNode node, int index) {
            this.node = node;
            this.index = index;
        }
    }
}