• 【牛客 - 剑指offer】JZ78 把二叉树打印成多行 两种方案(递归+非递归) Java实现



    剑指offer题解汇总 Java实现

    https://blog.csdn.net/guliguliguliguli/article/details/126089434

    本题链接

    知识分类篇 - 树 - JZ78 把二叉树打印成多行

    题目

    在这里插入图片描述
    在这里插入图片描述
    题目主要信息

    将一棵n个节点的二叉树按照从上到下按层的方式打印,每层按照从左到右的顺序输出

    方案一 LinkedList

    队列

    队列是一种仅支持在表尾进行插入操作、在表头进行删除操作的线性表,插入端称为队尾,删除端称为队首。它满足先进先出的性质,元素入队即将新元素加在队列的尾,元素出队即将队首元素取出,他后一个作为新的队值。

    创建一个LinkedList对象,用来存储每一层的、按照从左到右顺序的所有节点

    题目所给的二叉树并不是一棵完全二叉树,所以需要用一个变量cnt记录下每一层的节点的个数

    在进入每一层时:

    1. 需要创建一个arrayList存储当前这一层的、按照从左到右顺序的节点的值

    2. 需要弹出LinkedList中的、位于第一位的节点

    3. 如果该节点有左子节点或者右子节点,还需要向队列中添加,添加的过程中也需要计数,因为新添加到LinkedList中的节点数,就是遍历到下一层时,需要弹出的节点个数

    4. 最后将创建的arrayList添加到要返回的ArrayList>中

    import java.util.*;
    import java.util.ArrayList;
    
    /*
    public class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;
    
        public TreeNode(int val) {
            this.val = val;
    
        }
    
    }
    */
    public class Solution {
        ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
            ArrayList<ArrayList<Integer>> lists = new ArrayList<>();
            if (pRoot == null) {
                return lists;
            }
    
            LinkedList<TreeNode> queue = new LinkedList<>();
            TreeNode node;
            int cnt = 1;//记录每一层添加的节点数
            int nextCnt;//记录下一层添加了几个节点
            queue.add(pRoot);
    
            while (!queue.isEmpty()) {
    
                ArrayList<Integer> list = new ArrayList<>();
                nextCnt = 0;
                //遍历当前的LinkedList,取出值,添加到arraylist中
                for (int i = 0; i < cnt; i++) {
                    node = queue.pop();
                    list.add(node.val);
                    if (node.left != null) {
                        queue.add(node.left);
                        nextCnt++;
                    }
                    if (node.right != null) {
                        queue.add(node.right);
                        nextCnt++;
                    }
                }
                cnt = nextCnt;
                lists.add(list);
            }
            return lists;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    官方给的代码中,没有使用cnt和nextCnt的遍历来记录当层的节点数和下一层的节点数,而是直接使用queue.size()这个方法获取

    import java.util.*;
    import java.util.ArrayList;
    
    
    /*
    public class TreeNode {
        int val = 0;
        TreeNode left = null;
        TreeNode right = null;
    
        public TreeNode(int val) {
            this.val = val;
    
        }
    
    }
    */
    public class Solution {
        ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
            ArrayList<ArrayList<Integer>> lists = new ArrayList<>();
            if (pRoot == null) {
                return lists;
            }
    
            LinkedList<TreeNode> queue = new LinkedList<>();
            TreeNode node;
            queue.add(pRoot);
            int n;
    
            while (!queue.isEmpty()) {
    
                ArrayList<Integer> list = new ArrayList<>();
                n = queue.size();
                //遍历当前的LinkedList,取出值,添加到arraylist中
                for (int i = 0; i < n; i++) {
                    node = queue.pop();
                    list.add(node.val);
                    if (node.left != null) {
                        queue.add(node.left);
                    }
                    if (node.right != null) {
                        queue.add(node.right);
                    }
                }
                lists.add(list);
            }
            return lists;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    方案二 递归层次遍历

    递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因此递归过程,最重要的就是查看能不能将原本的问题分解为更小的子问题,这是使用递归的关键。

    而二叉树的递归,则是将某个节点的左子树、右子树看成一棵完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数不断进入子树。

    思路

    除了用队列非递归可以实现二叉树的层次遍历,还可以使用递归。但是递归的前序遍历访问二叉树不是按照层次的顺序,但是因为“根、左、右”的次序,我们能保证每一层一定是左边的元素先访问,后面再访问到同一层右边的元素。

    要找到这个节点是第几层的,只是需要在函数中加入记录深度的变量,每往下一层深度加1,同时保存结果的数组正好对应每层一个数组,因此,数字的大小刚好是遍历的深度,由此可以实现递归

    具体做法

    1. 记录输出的二维数组初始化为空

    2. 从根节点开始,深度为1开始进行遍历,当前节点有值递归内容才继续进行,否则返回

    3. 如果记录输出的二维数组长度小于当前层数,说明新到了一层,需要新开辟一个一维数组加到最后

    4. 因为“根、左、右”的顺序,同一层左边必定先访问,只需要根据层数在二维数组中找到相应的行号,添加在该行末尾就一定是层次遍历的顺序

    import java.util.*;
    
    public class Solution {
    
        private ArrayList<ArrayList<Integer>> res = new ArrayList<>();
    
        private void traverse(TreeNode root, int depth) {
            if (root != null) {
                //数组长度小于当前层数,新开一层
                if (res.size() < depth)
                    res.add(new ArrayList<>());
                //数组从0开始计数因此减1,在节点当前层的数组中插入节点
                res.get(depth - 1).add(root.val);
                //递归左右时节点深度记得加1
                traverse(root.left, depth + 1);
                traverse(root.right, depth + 1);
            }
        }
        //层次遍历
        public ArrayList<ArrayList<Integer>> Print(TreeNode pRoot) {
    
            //树的层级从1开始递归计数
            traverse(pRoot,  1);
            return res;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    MySQL高级篇05【索引的数据结构】
    antd-design-vue Table组件全局配置(分页器...)
    JS装饰器的介绍
    数据结构与算法介绍与学习路线
    列出连通集
    275. 传统文化青铜器主题网页 大学生期末大作业 Web前端网页制作 html+css
    不重装系统,如何将系统从SSD迁移到M2固态硬盘
    Gym 104025 M -Counting in Tree
    毕业设计-深度学习机器视觉铝型材表面缺陷识别
    话题挑战赛第2期来啦,五千元现金+周边等你瓜分!
  • 原文地址:https://blog.csdn.net/guliguliguliguli/article/details/126845072