leetcode每日一题系列——从上到下打印二叉树 II

144 阅读2分钟

这是我参与8月更文挑战的第27天,活动详情查看:8月更文挑战

题目描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。

例如:
给定二叉树: [3,9,20,null,null,15,7],

    3
   / \
  9  20
    /  \
   15   7

返回其层次遍历结果:

[
  [3],
  [9,20],
  [15,7]
]

提示:

  • 节点总数 <= 1000

题解

方法一:层序遍历 BFS

解题思路

  1. 按层打印:题目要求的二叉树的 从上至下 打印(即按层打印),又称为二叉树的 广度优先搜索(BFS)。BFS 通常借助 队列 的先入先出特性来实现。
  2. 每层打印到一行:将本层全部节点打印到一行,并将下一层全部节点加入队列,以此类推,即可分为多层打印。

image.png

算法流程

  1. 特例处理:当根节点为空,则返回空列表 []

  2. 初始化:打印结果列表 res = [],包含根节点的队列 queue = [root]

  3. BFS 循环:当队列 queue 为空时跳出;

    1. 新建一个临时列表 tmp,用于存储当前层打印结果;

    2. 当前层打印循环:循环次数为当前节点数(即队列 queue长度);

      1. 出队:队首元素出队,记为 node
      2. 打印:将 node.val 添加至 tmp 尾部;
      3. 添加子节点:若 node 的左(右)子节点不为空,则将左(右)子节点加入队列(queue);
    3. 将当前层结果 tmp 添加入 res

  4. 返回值:返回打印结果列表 res 即可。

代码

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        List<List<Integer>> res = new ArrayList<>();
        if(root != null) queue.add(root);
        while(!queue.isEmpty()) {
            List<Integer> tmp = new ArrayList<>();
            for(int i = queue.size(); i > 0; i--) {
                TreeNode node = queue.poll();
                tmp.add(node.val);
                if(node.left != null) queue.add(node.left);
                if(node.right != null) queue.add(node.right);
            }
            res.add(tmp);
        }
        return res;
    }
}

复杂度分析

  • 时间复杂度 O(N)  :N 为二叉树的节点数量,即 BFS 需循环 N 次。
  • 空间复杂度 O(N)  :最差情况下,即当树为平衡二叉树时,最多有 N/2 个树节点 同时 在 queue 中,使用 O(N) 大小的额外空间。

个人理解

  1. for 循环for(表达式1;表达式2;表达式3),表达式1 只会执行一次,所以可以用来分层,且初始值为 queue.size(),在该循环中继续向队列中添加值也不影响分层结果。

  2. arrayList 和 LinkedList 的区别:从下面关于 ArrayList 和 LinkedList 的区别可以看到,队列用 LinkedList 更好,存储每层数据不用频繁的插入和删除,直接用 ArrayList 即可。

    1. ArrayList 的实现是基于数组,LinkedList 的实现是基于双向链表
    2. 对于随机访问,ArrayList 优于 LinkedList
    3. 对于插入和删除操作,LinkedList 优于 ArrayList
    4. LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。
  3. ArrayList 的一些方法

    1. 初始化ArrayList<Object> arrayList = new ArrayList<>();
    2. 大小arrayList.size();
    3. 添加arrayList.add(new Object());
    4. 判断对象是否在容器内(引用判断),返回 boolean 值arrayList.contains(new Object());
  4. LinkedList 的一些方法

    1. 初始化LinkedList<String> linkedList = new LinkedList<>();
    2. 在链表后添加元素linkedList.add("first");
    3. 在链表头部插入元素linkedList.addFirst("addFirst");
    4. 移除链表第一个元素linkedList.remove();
    5. 移除链表最后一个元素linkedList.removeLast();
    6. 查询并移除第一个元素linkedList.poll();
    7. 获取第一个元素,但不移除linkedList.peek()

题解来源

作者:jyd
链接:leetcode-cn.com/problems/co… 来源:力扣(LeetCode)

题目来源

来源:力扣(LeetCode)
链接:leetcode-cn.com/problems/co… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。