日记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
发布评论