• 力扣日记11.7-【二叉树篇】二叉树的层序遍历


    力扣日记:【二叉树篇】二叉树的层序遍历

    日期:2023.11.7
    参考:代码随想录、力扣

    102. 二叉树的层序遍历

    题目描述

    难度:中等

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

    示例 1:
    在这里插入图片描述

    输入:root = [3,9,20,null,null,15,7]
    输出:[[3],[9,20],[15,7]]

    示例 2:

    输入:root = [1]
    输出:[[1]]

    示例 3:

    输入:root = []
    输出:[]

    提示:

    • 树中节点数目在范围 [0, 2000] 内
    • -1000 <= Node.val <= 1000

    题解

    cpp ver
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
     *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
     *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
     * };
     */
    #define SOLUTION 2
    #if SOLUTION == 1   // 迭代遍历
    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
            // 层序遍历需要将二叉树按层保存在一个二维数组中
            // 思路:
            // 1. 首先记录队列长度size,即需要连续弹出的元素个数(某一层元素的个数)
            // 2. 每弹出一个元素后,将元素的左右节点加入队列
            // 3. 在连续弹出size个元素后,重新回到1
            queue<TreeNode*> q;
            vector<vector<int>> result;
            if (root != NULL) q.push(root);
            while (!q.empty()) {
                int size = q.size();    // 首先记录队列长度,即当前层元素个数
                vector<int> res;    // 存放当前层元素
                while (size--) {
                    TreeNode* node = q.front(); // 弹出元素
                    q.pop();
                    res.push_back(node->val);
                    // 将左右节点加入队列
                    if (node->left != NULL)     q.push(node->left);
                    if (node->right != NULL)    q.push(node->right);
                }
                // 将当前层元素加入数组
                result.push_back(res);
            }
            return result;
        }
    };
    #elif SOLUTION == 2 // 递归遍历
    class Solution {
    public:
        vector<vector<int>> levelOrder(TreeNode* root) {
            vector<vector<int>> result;
            if (root == NULL)   return result;
            int depth = 0;
            order(root, result, depth);
            return result;
        }
        void order(TreeNode* cur, vector<vector<int>>& result, int depth) {
            // 输入参数:当前节点, 结果集指针(需要为指针!), 当前节点所在层数
            // 终止条件:当前节点为空
            if (cur == NULL) return;
            // 处理逻辑:
            // 如果结果集大小(层数)与所需深度(depth从0开始)相等(即少一层),说明结果集需要增加一层来存放当前节点
            if (result.size() == depth) result.push_back(vector<int>());
            // 将当前节点加入结果集对应层(层数在参数已经指定)
            result[depth].push_back(cur->val);
            // 递归:将左节点当作根节点重复上述逻辑
            order(cur->left, result, depth + 1);    // depth + 1,表示第一个参数指定的节点所在层数为depth+1
            order(cur->right, result, depth + 1);   // 注意cur->right的深度与cur->left一样,不会受上面的递归影响
        }
    };
    #endif
    
    • 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
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    go ver
    /**
     * Definition for a binary tree node.
     * type TreeNode struct {
     *     Val int
     *     Left *TreeNode
     *     Right *TreeNode
     * }
     */
    func levelOrder(root *TreeNode) [][]int {
        // go中的队列可通过list实现
        /*
            import "container/list"
    
            // 创建一个新的双向链表
            queue := list.New()
    
            // 入队操作
            queue.PushBack(1)
    
            // 出队操作
            if queue.Len() > 0 {
                front := queue.Front()
                queue.Remove(front)
                fmt.Println("出队元素:", front.Value)
            }
        */
        queue := list.New()
        res := [][]int{}
        
        if root != nil {
            queue.PushBack(root)
        }
        for queue.Len() > 0 {
            // 记录当前队列长度
            size := queue.Len()
            vec := []int{}
            for size > 0 {
                // 弹出并写入结果
                front := queue.Front()
                node := queue.Remove(front).(*TreeNode) // 存进list之后类型会变为*list.Element,要转换为*TreeNode
                vec = append(vec, node.Val)
                // 左右节点入队列
                if node.Left != nil {
                    queue.PushBack(node.Left)
                }
                if node.Right != nil {
                    queue.PushBack(node.Right)
                }
                size -= 1
            }
            res = append(res, vec)
        }
        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
    • 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
    • 53
    • 54

    复杂度

    时间复杂度:
    空间复杂度:

    思路总结

    • 层序遍历写法较固定,可作为模板
      • 1.首先记录队列长度size,即需要连续弹出的元素个数(某一层元素的个数)
      • 2.每弹出一个元素后,将元素的左右节点加入队列
      • 3.在连续弹出size个元素后,重新回到1
    • 对于递归写法:
      • 输入参数:当前节点, 结果集指针(需要为指针!), 当前节点所在层数
      • 终止条件:当前节点为空
      • 处理逻辑:
        • 如果结果集大小(层数)与所需深度(depth从0开始)相等(即少一层),说明结果集需要增加一层来存放当前节点
        • 将当前节点加入结果集对应层(层数在参数已经指定)
        • 递归:分别将左右节点当作根节点重复上述逻辑
  • 相关阅读:
    python tk展示图片
    国内最受欢迎的电商API接口调用京东商品详情数据
    Linux高性能服务器编程 学习笔记 第十六章 服务器调制、调试和测试
    自动化测试—web自动化—selenium初识
    ElasticSearch+Kibana+Logstash实现日志可视化运维监控
    windows 下 QT Android 环境搭建(QGC 4.2.x + Qt 5.15.2)
    Keep-Alive中通过component多次加载同样的动态组件无法保持状态的解决办法
    Linux命令200例:dnsconf用于配置和管理域名解析服务
    JAVASE语法零基础——抽象类和接口
    数据结构(c语言版) 链表(单链表、双链表、循环单链表、循环双链表)
  • 原文地址:https://blog.csdn.net/weixin_45847708/article/details/134262432