![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/d8159cb861974c1aaece16806ae9f4c1.png)
1. 法一:广度优先遍历(队列)
因为每个结点都要出入队列两次,所以是O(2 * n)的时间复杂度
- 先入队列根节点
- 则队列中结点个数为第1层结点个数
- 出队列根节点,然后将左右孩子入队列
- 回到第二不,当前队列中的左右孩子就是第二层的结点个数
- 继续第3步,出队列第二层的结点,同时将左右孩子入队列
- 以此类推直到队列中没有结点。
- 注意,每次出队列时,要先保存当前队列的size(),然后循环输出,否则每出队列一个元素,都会将其孩子入队列,会一直遍历下去,直到队列空。
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9ac774fc5dec4ee2be27fe3cb529c6b2.png)
class Solution {
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<>();
queue.offer(root);
while(!queue.isEmpty()){
List<Integer> level = new ArrayList<>();
int currentLevelSize = queue.size();
for(int i = 1;i <= currentLevelSize; i++){
TreeNode node = queue.poll();
level.add(node.val);
if(node.left!=null) queue.offer(node.left);
if(node.right!=null) queue.offer(node.right);
}
result.add(level);
}
return result;
}
}
1. 法二:深度优先遍历(递归)
每个结点都只访问一次,所以是O(n)的时间复杂度,比上面那个广度优先的实现,每个结点都少存取了一次
- 先遍历根结点,设置为0层,并创建一个容器专门保存0层的结点
- 然后遍历左孩子,设置为当前层+1层,并创建一个容器专门保存当前层+1层的结点
- 递归遍历左孩子完成后,然后遍历右孩子,同样为当前层+1,保存在对应层的容器中
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0c969a64a10a451c94de9165978b3d0c.png)
class Solution {
private void dfs(TreeNode root, int depth, List<List<Integer>> result) {
if (root == null) return;
if (result.size() == depth) result.add(new ArrayList<>());
result.get(depth).add(root.val);
dfs(root.left, depth + 1, result);
dfs(root.right, depth + 1, result);
}
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
dfs(root, 0, result);
return result;
}
}