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

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

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

102. 二叉树的层序遍历

题目描述

难度:中等

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

示例 1:
力扣日记11.7-【二叉树篇】二叉树的层序遍历_第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
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.首先记录队列长度size,即需要连续弹出的元素个数(某一层元素的个数)
    • 2.每弹出一个元素后,将元素的左右节点加入队列
    • 3.在连续弹出size个元素后,重新回到1
  • 对于递归写法:
    • 输入参数:当前节点, 结果集指针(需要为指针!), 当前节点所在层数
    • 终止条件:当前节点为空
    • 处理逻辑:
      • 如果结果集大小(层数)与所需深度(depth从0开始)相等(即少一层),说明结果集需要增加一层来存放当前节点
      • 将当前节点加入结果集对应层(层数在参数已经指定)
      • 递归:分别将左右节点当作根节点重复上述逻辑

你可能感兴趣的:(leetcode,算法,职场和发展)