leetcode
leetcode 651 ~ 700
N 叉树的层序遍历

N 叉树的层序遍历

难度:

标签:

题目描述

给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。

树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。

 

示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]

示例 2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[[1],[2,3,4,5],[6,7,8,9,10],[11,12,13],[14]]

 

提示:

  • 树的高度不会超过 1000
  • 树的节点总数在 [0, 10^4] 之间

代码结果

运行时间: 30 ms, 内存: 17.6 MB


// 思路:
// 1. 使用广度优先搜索(BFS)遍历树的每一层。
// 2. 使用Java Stream API来简化部分操作。

import java.util.*;
import java.util.stream.Collectors;

class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int val) {
        this.val = val;
    }

    public Node(int val, List<Node> children) {
        this.val = val;
        this.children = children;
    }
}

class Solution {
    public List<List<Integer>> levelOrder(Node root) {
        if (root == null) return Collections.emptyList();
        Queue<Node> queue = new LinkedList<>();
        queue.offer(root);
        List<List<Integer>> result = new ArrayList<>();

        while (!queue.isEmpty()) {
            int size = queue.size();
            List<Integer> level = new ArrayList<>();
            List<Node> nextLevel = new ArrayList<>();

            for (int i = 0; i < size; i++) {
                Node node = queue.poll();
                level.add(node.val);
                nextLevel.addAll(node.children);
            }

            result.add(level);
            queue.addAll(nextLevel);
        }

        return result;
    }
}

解释

方法:

这个题解使用了广度优先搜索(BFS)的思路来实现 N 叉树的层序遍历。具体步骤如下: 1. 首先判断根节点是否为空,如果为空则直接返回空列表。 2. 初始化结果列表 ans 和队列 stack,并将根节点加入队列。 3. 当队列不为空时,进行如下操作: - 初始化下一层节点的队列 nxt 和当前层节点值的临时列表 t。 - 遍历当前队列中的每个节点 x: - 将节点值加入临时列表 t。 - 遍历节点 x 的子节点,将它们加入下一层节点的队列 nxt。 - 将当前层的节点值列表 t 加入结果列表 ans。 - 将下一层节点的队列 nxt 赋值给 stack,开始下一轮循环。 4. 返回结果列表 ans,即为 N 叉树的层序遍历结果。

时间复杂度:

O(n)

空间复杂度:

O(n)

代码细节讲解

🦆
在算法中,你如何处理N叉树中的null值?
在本题解中,N 叉树的节点的子节点列表可以包括 null 值,但我们在遍历子节点时并没有特别处理这些 null 值。这是因为在 Python 中,遍历列表时会自动跳过 null 值,不会将它们加入到队列中。因此,算法仅处理有效的非 null 子节点。如果在其他编程环境中必须手动处理 null 值,可以在将子节点加入队列之前添加一个判空条件。
🦆
实现层序遍历时,为何选择使用队列而不是栈或其他数据结构?
层序遍历要求按照从上到下、从左到右的顺序访问所有节点。使用队列(先进先出)可以自然地实现这一过程:每次从队列的前端移除当前节点,并将其子节点按顺序加入队列的后端。如果使用栈(后进先出),则会导致节点的访问顺序颠倒,无法实现层序遍历。其他数据结构如列表也可以实现,但操作复杂且效率较低。
🦆
在队列中存储每一层的节点时,有没有考虑到队列可能会过大的情况,特别是在树较宽时?
确实,在树结构特别宽时,队列可能会存储大量的节点,导致内存使用增加。在算法实现时,这种情况是必须考虑的。为了应对可能的内存问题,可以在实际应用中监控内存使用情况,并在树的宽度非常大时考虑使用更高效的数据结构或优化树的结构。此外,也可以通过优化算法逻辑来减少内存的使用,例如通过链接节点而不是复制节点信息。
🦆
如果树的结构更改(例如添加或删除节点),算法的哪个部分需要调整以应对这些变化?
如果树的结构在遍历过程中发生变化(如添加或删除节点),主要需要关注的是如何保证遍历过程的一致性和正确性。在本算法中,由于我们使用的是队列来控制遍历,如果在遍历过程中修改了树(如添加或删除节点),可能需要同步更新队列中的元素。具体来说,如果添加节点,需要确保这些节点在正确的层次被加入队列;如果删除节点,则需要确保队列中不再引用已删除的节点。这通常要求树结构操作和遍历操作需要良好的同步机制,以防止冲突和错误。

相关问题

二叉树的层序遍历

给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

 

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

示例 2:

输入:root = [1]
输出:[[1]]

示例 3:

输入:root = []
输出:[]

 

提示:

  • 树中节点数目在范围 [0, 2000]
  • -1000 <= Node.val <= 1000

N 叉树的前序遍历

给定一个 n 叉树的根节点  root ,返回 其节点值的 前序遍历

n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。


示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[1,3,5,6,2,4]

示例 2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[1,2,3,6,7,11,14,4,8,12,5,9,13,10]

 

提示:

  • 节点总数在范围 [0, 104]
  • 0 <= Node.val <= 104
  • n 叉树的高度小于或等于 1000

 

进阶:递归法很简单,你可以使用迭代法完成此题吗?

N 叉树的后序遍历

给定一个 n 叉树的根节点 root ,返回 其节点值的 后序遍历

n 叉树 在输入中按层序遍历进行序列化表示,每组子节点由空值 null 分隔(请参见示例)。

 

示例 1:

输入:root = [1,null,3,2,4,null,5,6]
输出:[5,6,3,2,4,1]

示例 2:

输入:root = [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]
输出:[2,6,14,11,7,3,12,8,4,13,9,10,5,1]

 

提示:

  • 节点总数在范围 [0, 104]
  • 0 <= Node.val <= 104
  • n 叉树的高度小于或等于 1000

 

进阶:递归法很简单,你可以使用迭代法完成此题吗?