前言
本文主要介绍如何按层次遍历一棵二叉树,并把遍历的结果放到集合中。
需求描述
给出一个二叉树的根节点 root ,然后返回其节点值的层序遍历,每一层从左到右进行遍历,返回数据时,从下往上进行返回。
示例如下:
如下图所示,拿到一个二叉树后,从下往上、从左到右按层进行遍历,输出结果为:[[8, 9], [4, 5, 6, 7], [2, 3], [1]]。
思路分析
之前我们在遍历二叉树时,都是从上往下进行遍历,其实题目中可以从上往下进行遍历好,然后把结果再做一个逆序排列就好了。
按照示例图中,先来看下每一层遍历的结果是什么:
- 第1层:[1]
- 第2层:[2, 3]
- 第3层:[4,5,6,7]
- 第4层:[8, 9]
那怎么把每一层的节点值放到集合中呢?
- 步骤1
-
- 先把头结点放入一个队列中
- 步骤2
-
- 判断队列中的
size,size是多少,则就执行步骤3多少次
- 判断队列中的
- 步骤3
-
- 准备好一个集合,用来准备队列中弹出的元素,每一层对应一个集合,将弹出的元素放入集合中。
- 判断弹出元素是否有子节点,如果有的话,将子节点加入队列中。
用示例图中的二叉树,来看一下具体过程:
- 节点
1进入队列,此时队列的size为1,执行步骤 2``1次,将节点1弹出,创建一个集合将节点的值放进入。 - 将节点
1的子节点加入队列,从左往右,节点2先进入队列,节点3后进入队列。 - 此时队列长度为
2,现将节点2弹出,将子节点4和子节点5放入队列,再将节点3弹出,将节点3的子节点6、7放入队列,此时队列中的数据为4、5、6、7,创建一个集合将弹出去的节点2、3放进去。 - 依次类推,安装这个步骤,就能实现一棵二叉树的层次遍历。
经过上面的步骤,我们已经分析出了如何从上往下按层次收集一棵二叉树的节点,那么如何逆序呢?
因为收集起来的元素是放入一个集合中的,可以直接把集合进行反转即可。
思路优化
但是集合的反转会带来额外的时间开销,有没有更好的办法呢?
我们可以使用一个链表(LinkedList)来代替集合(ArrayList),在往前面放入一个元素时,链表只需要把节点间的关系关联上即可,而集合需要一次一次的挪动元素。
例如,现在集合中有4个元素[1,2,3,4],如果想在1元素之前加入一个数的话,1,2,3,4这4个元素都需要往后挪动一下,如果是链表的话,直接插入即可,所以使用链表效率会更高一些。
代码实现
根据上面的思路分析,来看一下代码是如何实现的:
首先定义二叉树的节点,代码如下:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
遍历二叉树的代码如下:
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new LinkedList<>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> curAns = new LinkedList<>();
for (int i = 0; i < size; i++) {
TreeNode curNode = queue.poll();
curAns.add(curNode.val);
if (curNode.left != null) {
queue.add(curNode.left);
}
if (curNode.right != null) {
queue.add(curNode.right);
}
}
ans.add(0, curAns);
}
return ans;
}
总结
本文主要介绍如何按层次遍历一棵二叉树,总体来说这个题目还是很简单的,当然还有其他更简单的实现方案,这里就不再介绍了~