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


        题目描述

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

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

        3
       / \
      9  20
          /  \
       15   7
       
    返回其层次遍历结果:

    [3,9,20,15,7]

    提示:

    节点总数 <= 1000

       思路

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

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

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

     代码

    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> 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
    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 queue = new LinkedList<>();
    30. ArrayList 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,得到所有按照层次组织的节点,这样就是从上到下,从左到右打印二叉树节点。 

    深度优先搜索 

    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> 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 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]],相信经过上面的深度优先搜索,大家也许有一些想法,这个代码或许简单改造一下就可以了。

  • 相关阅读:
    .md结尾的文件如何展示图片
    你也还在找程序员外包平台吗?有这几个就足够了!
    thinkphp5 扩展redis Linux搭建redis php搭建redis
    代码随想录算法训练营第十四天|二叉树理论基础|二叉树的递归遍历|二叉树的迭代遍历以及统一迭代
    C#根据DataTable中的不同值为asp:DataGrid中的不同行或单元格设置不同的颜色
    [树学习]-平衡二叉搜索树
    18.Pandas的数据转换函数map、apply、applymap
    【华为上机考试真题】汽水瓶
    自动化测试基础——Pytest框架之YAML详解以及Parametrize数据驱动
    22-9-17学习笔记
  • 原文地址:https://blog.csdn.net/feinifi/article/details/133378286