剑指offer32Ⅰ:从上到下打印二叉树

清疚 2024-02-28 06:42 165阅读 0赞

题目描述

从上到下按层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印到一行。
例如:

给定二叉树: [3,9,20,null,null,15,7],

3
/ \
9 20
/ \
15 7

返回其层次遍历结果:

[3,9,20,15,7]

提示:

节点总数 <= 1000

思路

这个题目的意思很明确,就是从根节点开始,一层一层打印节点,而且节点顺序是从左到右。以上面示例为例,3为根节点,之后打印它的左右节点9,20,之后再打印20的子节点15,7。全部打印完成结束。

这道题有点类似图算法中的广度优先搜索,先从顶端开始,依次遍历图的下一层节点,下一层节点遍历完成,接着遍历下下一层。仅仅依赖树结构的左右节点关系,然后递归遍历,我们无法得到最终结果,因为随着层数的增加,兄弟节点之间没有必然关系,他们无法保证从左到右来遍历。

这里我们需要借助一个队列来存放遍历过的节点,这样,每遍历依次,后续的遍历,我们从队列开头取元素,这样就可以保证按照层级和左右顺序来打印树节点。

cff6ab571c3c441ea0e81ac20f594f0b.png

代码

  1. package com.xxx.example;
  2. import java.util.ArrayList;
  3. import java.util.LinkedList;
  4. import java.util.List;
  5. import java.util.Queue;
  6. public class Offer32PrintTreeNode {
  7. private static TreeNode root;
  8. private static List<List<Integer>> nodeList = new ArrayList<>();
  9. public static void main(String[] args) {
  10. TreeNode treeNode = new TreeNode(3);
  11. TreeNode treeNode1 = new TreeNode(9);
  12. TreeNode treeNode2 = new TreeNode(20);
  13. TreeNode treeNode3 = new TreeNode(15);
  14. TreeNode treeNode4 = new TreeNode(7);
  15. root = treeNode;
  16. treeNode2.left = treeNode3;
  17. treeNode2.right = treeNode4;
  18. root.left = treeNode1;
  19. root.right = treeNode2;
  20. int[] result = levelOrder(root);
  21. for(int i=0;i<result.length;i++) {
  22. System.out.print(result[i] + " ");
  23. }
  24. System.out.println();
  25. }
  26. public static int[] levelOrder(TreeNode root) {
  27. if (root == null)
  28. return new int[0];
  29. Queue<TreeNode> queue = new LinkedList<>();
  30. ArrayList<Integer> list = new ArrayList<>();
  31. queue.add(root);
  32. while (!queue.isEmpty()) {
  33. TreeNode curNode = queue.poll();
  34. list.add(curNode.val);
  35. if (curNode.left != null)
  36. queue.add(curNode.left);
  37. if (curNode.right != null)
  38. queue.add(curNode.right);
  39. }
  40. return list.stream().mapToInt(Integer::intValue).toArray();
  41. }
  42. }
  43. class TreeNode {
  44. int val;
  45. TreeNode left;
  46. TreeNode right;
  47. TreeNode(int value) {
  48. this.val = value;
  49. this.left = null;
  50. this.right = null;
  51. }
  52. @Override
  53. public String toString() {
  54. return val + "";
  55. }
  56. }

还有一种办法,其实就是利用深度优先搜索的思想解决,这个似乎有点玄妙,这里明明是要广度优先搜索,怎么还利用起深度优先搜索呢?其实是这样的,这里按照深度优先搜索,我们只是把搜到的数据打上标签,这个标签就是它的层次,也叫深度,每个深度的节点我们保存到同样深度的map映射里。最后,我们遍历map,得到所有按照层次组织的节点,这样就是从上到下,从左到右打印二叉树节点。

231a1e45a55242d78959ed881579b803.png

深度优先搜索

  1. package com.xxx.tutorial;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. public class TreeNodeTraversal {
  7. private static Map<Integer, List<Integer>> map = new HashMap<>();
  8. private static int max = -1;
  9. private static int cnt = 0;
  10. public static void main(String[] args) {
  11. TreeNode node0 = new TreeNode(3);
  12. TreeNode node1 = new TreeNode(9);
  13. TreeNode node2 = new TreeNode(20);
  14. TreeNode node3 = new TreeNode(15);
  15. TreeNode node4 = new TreeNode(7);
  16. node0.left = node1;
  17. node0.right = node2;
  18. node2.left = node3;
  19. node2.right = node4;
  20. int[] res = traversal(node0);
  21. for (int i = 0; i < res.length; i++) {
  22. System.out.print(res[i] + " ");
  23. }
  24. System.out.println();
  25. }
  26. public static int[] traversal(TreeNode root) {
  27. dfs(root, 0);
  28. int[] ans = new int[cnt];
  29. for (int i = 0, idx = 0; i <= max; i++) {
  30. for (int x : map.get(i))
  31. ans[idx++] = x;
  32. }
  33. return ans;
  34. }
  35. public static void dfs(TreeNode node, int depth) {
  36. if (node == null) return;
  37. max = Math.max(max, depth);
  38. cnt++;
  39. dfs(node.left, depth + 1);
  40. List<Integer> list = map.getOrDefault(depth, new ArrayList<>());
  41. list.add(node.val);
  42. map.put(depth, list);
  43. dfs(node.right, depth + 1);
  44. }
  45. public static class TreeNode {
  46. int val;
  47. TreeNode left;
  48. TreeNode right;
  49. public TreeNode(int value) {
  50. this.val = value;
  51. this.left = null;
  52. this.right = null;
  53. }
  54. }
  55. }

这里通过递归调用,我们能遍历完所有节点,并按照深度层次保存各自深度的节点。

这个思路很巧妙,它利用深度层次来映射对应的节点,最后,我们遍历map映射得到所有节点,他们的顺序正好是从上到下,从左到右。

剑指offer打印二叉树还有另一个题目,就是按照层次打印二叉树,就是[[3],[9,20],[15,7]],相信经过上面的深度优先搜索,大家也许有一些想法,这个代码或许简单改造一下就可以了。

发表评论

表情:
评论列表 (有 0 条评论,165人围观)

还没有评论,来说两句吧...

相关阅读