给定一个 N 叉树,返回其节点值的层序遍历。(即从左到右,逐层遍历)。
树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例)。
示例 1:
输入:root = [1,null,3,2,4,null,5,6]
输出:[[1],[3,2,4],[5,6]]
示例 2:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T5zy2R4c-1649379122062)(assets/sample_4_964.png)]
输入: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]
之间BFS忘得差不多了,直接看官方解法吧(摆烂ing…)
方法一:广度优先搜索
思路与算法对于「层序遍历」的题目,我们一般使用广度优先搜索。在广度优先搜索的每一轮中,我们会遍历同一层的所有节点。
具体地,我们首先把根节点 root 放入队列中,随后在广度优先搜索的每一轮中,我们首先记录下当前队列中包含的节点个数(记为 cnt),即表示上一层的节点个数。在这之后,我们从队列中依次取出节点,直到取出了上一层的全部 cnt 个节点为止。当取出节点 cur 时,我们将 cur 的值放入一个临时列表,再将cur 的所有子节点全部放入队列中。
当这一轮遍历完成后,临时列表中就存放了当前层所有节点的值。这样一来,当整个广度优先搜索完成后,我们就可以得到层序遍历的结果。
细节
需要特殊判断树为空的情况。
于是我阅读了官方解法,认真理解后,自己写了出来(我真的没有偷看。。)
/*
// Definition for a Node. 官方后台对Node结点的实现
class Node {
public int val;
public List children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List _children) {
val = _val;
children = _children;
}
};
*/
//附带一点点理解性的注释
class Solution {
public List<List<Integer>> levelOrder(Node root) {
//判断空树,如果不写,输入[]则会出现NullPointException
if (root==null) return new ArrayList<List<Integer>>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();//答案的二维数组列表
Queue<Node> queue = new ArrayDeque<Node>();//队列
queue.offer(root);//先将root入队
//当队列非空时,对每一层结点执行以下操作(初始时队列中有一个root结点),当所有叶子结点入队后,则为最后一次执行
while(!queue.isEmpty()){
//记录当前一层的结点数,因为下面的操作会一边将结点加入临时列表,一边又将新的孩子结点入队,需要一个cnt来控制这一轮进入临列表的结点数
int cnt = queue.size();
List<Integer> level = new ArrayList<Integer>();//临时列表
for(int i=0;i<cnt;i++){//用cnt的限制,遍历当前一层的结点
Node cur = queue.poll();//出队一个结点
level.add(cur.val);//将结点值加入临时列表
for (Node child : cur.children){
queue.offer(child);//将该结点所有孩子结点入队
}
}
ans.add(level);//一层遍历结束,将临时列表加入答案的二维列表中
}
return ans;//队列为空,遍历结束,返回结果
}
}
总之,基本的数据结构还是要多熟悉,总体上的架构做好了,才能够保证每个细节部分的正常运作。