力扣日记11.7

编程入门 行业动态 更新时间:2024-10-08 18:32:23

力扣<a href=https://www.elefans.com/category/jswz/34/1768372.html style=日记11.7"/>

力扣日记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个元素后,重新回到1queue<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+1order(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,要转换为*TreeNodevec = 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开始)相等(即少一层),说明结果集需要增加一层来存放当前节点
      • 将当前节点加入结果集对应层(层数在参数已经指定)
      • 递归:分别将左右节点当作根节点重复上述逻辑

更多推荐

力扣日记11.7

本文发布于:2023-11-16 02:49:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1611588.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:日记

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!