求一颗二叉树的宽度

简介: 求一颗二叉树的宽度

前言

如何完成二叉树的宽度优先遍历(常见题目:求一颗二叉树的宽度)

二叉树的宽度优先遍历

以下面的二叉树为例:


image.png


如果对其进行宽度优先遍历,打印出来的顺序是1,2,3,4,5,6,7

Java版

public static void w(Node head){
    if(head == null){
        return;
    }
    Queue<Node> queue = new LinkedList<>();
    queue.add(head);
    while(!queue.isEmpty()){
        Node cur = queue.poll();
        System.out.printIn(cur.value);
        if(cur.left != null){
            queue.add(cur.left);
        }
        if(cur.right != null){
            queue.add(cur.right);
        }
    }
}
复制代码

求一颗二叉树的宽度

题目分析

以下面的二叉树为例:

网络异常,图片无法展示
|

这个二叉树的最大宽度是3,位于第三层。

在上述对二叉树的宽度优先遍历的基础上,我们还需要在遍历时知道该节点位于第几层,以便于记录每一层中的节点个数。

public static void w(Node head){
    if(head == null){
        return;
    }
    Queue<Node> queue = new LinkedList<>();
    queue.add(head);
    HashMap<Node, Integer> levelMap = new HashMap<>();
    levelMap.put(head, 1);
    int curLevel = 1;
    int curLevelNodes = 0;
    int max = Integer.MIN_VALUE;
    while(!queue.isEmpty()){
        Node cur = queue.poll();
        int curNodeLevel = levelMap.get(cur);
        if(curNodeLevel == curLevel){
            curLevelNodes++;
        }else{
            curLevel++;
            curLevelNodes=1;
        }
        max = Math.max(max, curLevelNodes);
        if(cur.left != null){
            levelMap.put(cur.left, curNodeLevel+1);
            queue.add(cur.left);
        }
        if(cur.right != null){
            levelMap.put(cur.right, curNodeLevel+1);
            queue.add(cur.right);
        }
    }
    return max
}
复制代码

进阶:Leetcode- 662. 二叉树最大宽度

根据上面的例子,这道题好像也是广度优先遍历的一个例子,在其广度优先遍历的基础上,遍历时知道该节点位于哪一层,并记录该层的节点个数,但是好像,此法不通...因为它中间空的位置也要计算!

难点:两端点之间的null节点也计入长度

此时,我们可以利用完全二叉树的性质:

  • 对于一颗完全二插树,如果按照从上至下,从左往右对所有节点从零开始顺序编号
  • 则父节点的左孩子节点的序号:2i+1
  • 父节点的左孩子节点的序号:2i+2
var widthOfBinaryTree = function(root) {
    // 首先实现广度优先遍历,在其基础上,遍历时知道该节点位于哪一层,并记录该层的节点个数
    // 难点:两端点之间的null节点也计入长度
    // const queue = [root];
    // while(queue.length){
    //     const cur = queue.shift();
    //     console.log(cur.val);
    //     cur.left && queue.push(cur.left);
    //     cur.right && queue.push(cur.right);
    // }
    // 如果两端点之间的null节点不计入长度
    // const queue = [root];
    // const levelMap = new Map();
    // let curLevel = 1;
    // let max = 0;
    // let curLevelNodes = 0;
    // levelMap.set(root, 1);
    // while(queue.length>0){
    //     const cur = queue.shift();
    //     const curNodeLevel = levelMap.get(cur);
    //     if(curNodeLevel === curLevel){
    //         curLevelNodes++;
    //     }else{
    //         curLevel++;
    //         curLevelNodes = 1;
    //     }
    //     max = Math.max(max, curLevelNodes);
    //     if(cur.left){
    //         queue.push(cur.left);
    //         levelMap.set(cur.left, curNodeLevel+1);
    //     }
    //     if(cur.right){
    //         queue.push(cur.right);
    //         levelMap.set(cur.right, curNodeLevel+1)
    //     }
    //     console.log(cur, curNodeLevel, curLevel, curLevelNodes, max) ;
    // }
    // return max
    const max = [];
    function dfs(node, dep, idx) {
        if (!node) return;
        max[dep] = (max[dep] || [idx, idx]);
        max[dep][0] = Math.min(max[dep][0], idx);
        max[dep][1] = Math.max(max[dep][1], idx);
        dfs(node.left, dep + 1, (idx << 1) + 1);
        dfs(node.right, dep + 1, (idx << 1) + 2);
    }
    dfs(root, 0, 0);
    return max.reduce((max, [l, r]) => Math.max(max, r - l), 0) + 1;
};



相关文章
|
4月前
|
NoSQL 容器 消息中间件
树的直径、最近公共祖先、树的变形
树的直径、最近公共祖先、树的变形
|
7月前
|
存储 算法
【每日挠头算法题(9)】二叉树的直径|二叉树的层序遍历
【每日挠头算法题(9)】二叉树的直径|二叉树的层序遍历
|
5月前
|
算法 程序员
【算法训练-二叉树 三】【最大深度与直径】求二叉树的最大深度、求二叉树的直径
【算法训练-二叉树 三】【最大深度与直径】求二叉树的最大深度、求二叉树的直径
38 0
|
4月前
AVLTree——高度平衡二叉搜索树
AVLTree——高度平衡二叉搜索树
41 0
|
4月前
|
C++
翻转二叉树(C++)
翻转二叉树(C++)
17 0
|
9月前
|
人工智能 BI
LeetCode-310 最小高度树
LeetCode-310 最小高度树
|
7月前
【Leetcode -404.左子叶之和 -543.二叉树的直径】
【Leetcode -404.左子叶之和 -543.二叉树的直径】
26 0
|
11月前
二叉树最大宽度
二叉树最大宽度
42 0
二叉树的层序遍历、二叉树叶节点输出算法、求二叉树的高度、层序创建一棵二叉树
二叉树的层序遍历、二叉树叶节点输出算法、求二叉树的高度、层序创建一棵二叉树
|
存储 C++
求二叉树的高度(C++递归实现)
求二叉树的高度(C++递归实现)
90 0