二叉树--二叉树的宽度

Posted 算法和数据结构

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉树--二叉树的宽度相关的知识,希望对你有一定的参考价值。

来源:LeetCode

难度:中等

描述:

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

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


示例1:


示例2:


分析:

        注意本题中的宽度并不是每层的节点个数,而是基于整棵树是满二叉树的情况下,每层的宽度则为两个端点加上中间满二叉树缺失的节点的总个数

       因此咱们只要计算出每个节点在满二叉树的情况下,在本层的所属的位置,那么本层的宽度就是两个端点的位置差。在满二叉树中,假设根节点的位置为position,那么左子节点的位置为position * 2,右子节点的位置为position * 2 + 1,通过上面的公式很容易就能得到每个节点所属位置。具体解法如下


解题

方法一:深度优先遍历

思路:

        首先咱们需要记录每个节点的位置,假设根节点的位置为position,左节点为position * 2,右节点则为position * 2 + 1

        其次采用深度遍历的方式遍历二叉树,每层第一个被遍历的节点就是该层的最左边的节点,因此采用map将每层的深度和其最左节点记录下来,所以每层的宽度则是该深度下最右边的位置减去 最左边的位置 加 1

        记录每层的宽度,并保留最大值即可


代码:

 1private int ans;
2public int widthOfBinaryTree(TreeNode root) {
3    Map<Integer, Integer> dept2LeftPosition = new HashMap<>();
4    dfs(root, 00, dept2LeftPosition);
5    return ans;
6}
7public void dfs(TreeNode root, int depth, int pos,
8                Map<Integer, Integer> dept2LeftPosition)
 
{
9    if (root == null) {
10        return;
11    }
12    if (!dept2LeftPosition.containsKey(depth)) {
13        //记录每层的最左边位置
14        dept2LeftPosition.put(depth, pos);
15    }
16    //ans = max(每个节点位置 - 本层中最左节点位置 + 1, ans)
17    ans = Math.max(ans, pos - dept2LeftPosition.get(depth) + 1);
18    //递归左右子树
19    dfs(root.left, depth + 12 * pos, dept2LeftPosition);
20    dfs(root.right, depth + 12 * pos + 1, dept2LeftPosition);
21}

时间复杂度:O(n) n是节点个数

空间复杂度:O(n) 


方法二:广度优先遍历

思路:

        每个节点位置的计算公式和上面一样,只是这里采用队列存储每一层的节点,同理采用一个链表记录每个节点对应的位置。

        当队列的节点出队时,其对应的位置也从链表中移除,这样保证了链表中的位置是严格按照节点进入队列的位置来排列的,即链表头是每层中最左节点位置,链表尾是每层中最右节点位置。

        因此每层宽度等于链表尾的值 - 链表头的值 + 1


代码:

 1public int widthOfBinaryTree(TreeNode root) {
2    if (root == null) {
3        return 0;
4    }
5    //利用队列存储每层节点
6    Queue<TreeNode> queue = new LinkedList<>();
7    //利用List链表存储每层中每个节点的位置
8    LinkedList<Integer> list = new LinkedList<>();
9    queue.offer(root);
10    list.add(1);
11    int res = 1;
12    while (!queue.isEmpty()) {
13        int size = queue.size();
14        for (int i = 0; i < size; i++) {
15            //节点出队
16            TreeNode cur = queue.poll();
17            //节点出队的同时将其对应的位置移除链表,
18            //当本层节点全部出队时,其所有对应的节点也将全部移除链表
19            Integer curIndex = list.removeFirst();
20            if (cur.left != null) {
21                queue.offer(cur.left);
22                //存储每个节点位置
23                list.add(curIndex * 2);
24            }
25            if (cur.right != null) {
26                queue.offer(cur.right);
27                list.add(curIndex * 2 + 1);
28            }
29        }
30        // list 中 size 为 1 的情况下,宽度也为 1,没有必要计算。
31        if (list.size() >= 2) {
32            //每层的宽度 = 最右边的位置 - 最左边的位置 + 1
33            res = Math.max(res, list.getLast() - list.getFirst() + 1);
34        }
35    }
36    return res;
37}

时间复杂度:O(n) n是节点个数

空间复杂度:O(n) 


往期精彩推荐



扫描下方二维码,关注公众号,更多精彩等你发现



以上是关于二叉树--二叉树的宽度的主要内容,如果未能解决你的问题,请参考以下文章

python-leetcode102-树的宽度遍历二叉树的层次遍历

给定一个二叉树,获取该二叉树的宽度深度

计算二叉树的宽度的两种方式

计算二叉树的宽度的两种方式

python-leetcode103-树的宽度遍历二叉树的锯齿形层次遍历

以二叉链表为存储结构,写出求二叉树高度和宽度的算法