这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战
给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]
今天我们就来聊一聊我们的树,树可能是我们2所学的数据结构当中最难理解的变种最多的了,之前也一直抗拒做树相关的题,但是你也不能不做啊,你得硬着头皮上啊,
回顾深度和广度遍历
首先需要先介绍我们树相关的两种遍历,我们的深度遍历和广度遍历,这两中遍历的方式我猜大家应该都知道,我就简单的写一下实现
深度遍历,实现深度最简单的办法就是递归了,
void dfs(TreeNode root) {
if (root == null) {
return;
}
dfs(root.left);
dfs(root.right);
}
广度遍历就比深度遍历看起来要复杂很多,我们使用了队列来维护
void bfs(TreeNode root) {
Queue<TreeNode> queue = new ArrayDeque<>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
}
}
其实,我们这两种排序都使用了数据结构,我们深度排序因为使用的是递归,他用隐匿的方式调用了栈的结构
对于深度遍历就不说过多的解读了
我们详细了解一下我们广度遍历在队列的存储过程
- 节点1入队,节点1出队,访问节点1
- 节点1的孩子节点2,3入队,节点2出队,访问节点2
- 节点2的孩子节点 4,5入队
- 节点3出队,访问就节点3
- 节点3的孩子节点6入队
- 节点4出队,访问节点4,没有孩子节点
- 节点5出队,访问节点5
- 节点5的孩子节点7 入队
- 节点6出队,访问节点6
- 节点6的孩子节点8,9入队
- 节点7,8,9出队
解题
我们深度和广度遍历了解之后,我们一下子就能发现我们这道题使用广度遍历,做起来可能更容易一些。 但我们仔细读题,我们需要将一层的数据装入一个集合,那我们靠什么去分割呢?
我们仔细看一下上面广度遍历在队列中的入队和出队的顺序,
首先,只有父节点出队,子节点才会入队
所以我们可以推导出,我们上层节点全部出队,我们的下层节点全部入队,那我们就可以用此时的队列长度来分割
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if(root==null){
return result;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()) {
//创建集合来实现我们队列
List<Integer> list = new ArrayList<Integer>();
//获取队列长度
int size = queue.size();
//i没有实际作用
for (int i = 0; i <size; i++){
//从队列中取出一个节点,判断他是否有子节点,有则入队
TreeNode node = queue.poll();
list.add(node.val);
if(node.left !=null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
result.add(list);
}
return result;
}