描述

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

示例:
image.png
返回:
[
[3],
[9, 20],
[15, 7]
]

思路

广度优先遍历(BFS)。
在之前做的题目中,涉及到前序,中序,后序遍历都是深度优先遍历(DFS),通常会通过递归的方式来实现DFS,优点是不用手动维护栈,代码简洁,易于记忆(三种遍历只用调整代码顺序即可)。

而BFS的实现则通常是通过迭代的方式,而不是递归。代码相对复杂,但是,有一些情况是递归不好实现的,比如说本题,用BFS才是正确的。

BFS的基本实现是基于队列(Queue)的,

  1. void bfs(TreeNode root) {
  2. Deque<TreeNode> queue = new ArrayDeque<>();
  3. List<Integer> result = new ArrayList<>();
  4. // 首先,入队root结点,入队总从最后入
  5. queue.addLast(root);
  6. while(!queue.isEmpty()) {
  7. // 出队,出队总从第一个出
  8. TreeNode temp = queue.pollFirst();
  9. // 添加到结果数组中
  10. result.add(temp.val);
  11. // 入队左结点
  12. if (temp.left != null) {
  13. queue.addLast(temp.left);
  14. }
  15. // 入队右结点
  16. if (temp.right != null) {
  17. queue.addLast(temp.right);
  18. }
  19. }
  20. }

在通过BFS遍历以后,result数组是一个一维数组,这与本题不相符,本题需要区分每一层。

因此只需要加一个size来记住每一层的结点数即可,修改后的代码如下:

  1. class Solution {
  2. public List<List<Integer>> levelOrder(TreeNode root) {
  3. List<List<Integer>> result = new ArrayList<>();
  4. // 记得判断空树,否则直接调用bfs会报错,空指针异常。
  5. if (root == null) {
  6. return result;
  7. }
  8. bfs(root, result);
  9. return result;
  10. }
  11. private void bfs(TreeNode root, List<List<Integer>> result) {
  12. Deque<TreeNode> queue = new ArrayDeque<>();
  13. // 首先,入队root结点,入队总从最后入
  14. queue.addLast(root);
  15. while(!queue.isEmpty()) {
  16. List<Integer> level = new ArrayList<>();
  17. // 保存size
  18. int size = queue.size();
  19. // 遍历次数为size次
  20. for (int i = 0; i < size; i++) {
  21. // 出队,出队总从第一个出
  22. TreeNode temp = queue.pollFirst();
  23. // 添加到结果数组中
  24. level.add(temp.val);
  25. // 入队左结点
  26. if (temp.left != null) {
  27. queue.addLast(temp.left);
  28. }
  29. // 入队右结点
  30. if (temp.right != null) {
  31. queue.addLast(temp.right);
  32. }
  33. }
  34. result.add(level);
  35. }
  36. }
  37. }