第三周:[LeetCode]102. Binary Tree Level Order Traversal

  1. Binary Tree Level Order Traversal
    Given a binary tree, return the level order traversal of its nodes’ values. (ie, from left to right, level by level).
    For example:
    Given binary tree [3,9,20,null,null,15,7],
    3
    / \
    9 20
    / \
    15 7
    return its level order traversal as:
    [
    [3],
    [9,20],
    [15,7]
    ]

其实就是对二叉树进行一遍广度优先搜索,每一层输出的结果保存为一个数组,用队列实现的时候维护count和next_count两个变量记录当前层需要遍历节点的个数以及下一层需要遍历节点的个数。


class Solution {
public:
    vector<vector<int> > levelOrder(TreeNode *root) {
       vector<vector<int>> ans;
        vector<int> level;
        if(root == NULL)
            return ans;
        queue<TreeNode*> q;
        q.push(root);
        int count = 1,next_count = 0;
        while(!q.empty()){
            TreeNode* node = q.front();
            level.push_back(node -> val);
            if(node -> left != NULL){
                q.push(node -> left);
                next_count ++;
            }
            if(node -> right != NULL){
                q.push(node -> right);
                next_count ++;
            }
            q.pop();
            count --;
            if(count == 0){
                ans.push_back(level);
                level.clear();
                count = next_count;
                next_count = 0;
            }
        }
        return ans;
    }
};
<think>我们有一个二叉树,需要实现层序遍历,即按层次从上到下,从左到右访问每个节点,并将每层的节点值分别存储在一个列表中,最终返回一个二维列表。 代码分析如下: 1. 导入:代码中使用了`deque`,它是`collections`模块中的双端队列,用于高效地执行队列操作(popleft和append)。 2. 类定义:题目给出了二叉树的节点定义(注释部分),每个节点有值、左子节点和右子节点。 3. 方法`levelOrder`: - 输入:二叉树的根节点`root`,类型为`Optional[TreeNode]`(即可能是`TreeNode`或`None`)。 - 输出:一个二维列表,每个子列表表示一层的节点值。 4. 具体步骤: a. 首先判断根节点是否为空,如果为空,直接返回空列表`[]`。 b. 初始化一个空列表`ans`用于存储结果。 c. 初始化一个队列`q`(使用`deque`),并将根节点加入队列。 d. 开始循环,条件是队列不为空: - 在每一层开始前,初始化一个空列表`vals`用于存储当前层的节点值。 - 使用一个内层循环,循环次数为当前队列的长度(即当前层的节点数): * 从队列左侧弹出一个节点`node`。 * 将`node`的值`val`添加到`vals`中。 * 如果该节点有左子节点,将左子节点加入队列。 * 如果该节点有右子节点,将右子节点加入队列。 - 内层循环结束后,当前层的所有节点值已经存储在`vals`中,将`vals`添加到`ans`中。 e. 当队列为空时,所有层遍历完毕,返回`ans`。 5. 关键点: - 使用队列实现广度优先搜索(BFS)。 - 内层循环的次数是当前层的节点数(即一开始队列的长度),这样能确保每次内层循环处理完一层。 - 在处理当前层节点的同时,将下一层的节点按顺序加入队列。 6. 示例: 考虑二叉树: 3 / \ 9 20 / \ 15 7 步骤: 初始:q = [3] 第一层:处理节点3,vals=[3],然后将9和20加入队列,q=[9,20] -> ans=[[3]] 第二层:处理节点9(弹出9,vals=[9];然后处理20,vals=[9,20]),将20的左子节点15和右子节点7加入队列,q=[15,7] -> ans=[[3],[9,20]] 第三层:处理节点15(vals=[15])和节点7(vals=[15,7]),没有子节点,q变为空 -> ans=[[3],[9,20],[15,7]] 7. 时间复杂度:O(n),其中n是节点个数,每个节点恰好被访问一次。 8. 空间复杂度:O(n),队列中元素个数最多为n(最坏情况,即最后一层的节点数)。 这个算法是标准的BFS层序遍历。 相关问题: §§相关问题§§: 1. 如果要求按层序遍历的顺序,但是要求从下到上输出每一层(即自底向上),如何修改代码? 2. 如何实现锯齿形层序遍历(即先从左到右,再从右到左,交替进行)? 3. 除了使用队列,还可以用哪些方法实现二叉树的层序遍历? 4. 如何只使用一个循环(不使用内层循环)实现层序遍历?这样做的缺点是什么?</think># 二叉树层序遍历(LeetCode 102)代码分析 ## 代码功能 这段代码实现了二叉树的**层序遍历**(Level Order Traversal),即逐层从左到右访问所有节点,并将每层的节点值存储在一个单独的列表中,最终返回二维列表。 ## 逐行代码分析 ```python from collections import deque # 导入双端队列用于高效实现队列操作 class Solution: def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: # 边界条件处理:空树直接返回空列表 if root is None: return [] ans = [] # 存储最终结果的二维列表 q = deque([root]) # 初始化队列,将根节点加入队列 # 主循环:当队列不为空时继续处理 while q: vals = [] # 存储当前层的节点值 # 关键点:处理当前层的所有节点 for _ in range(len(q)): # 当前层的节点数量 node = q.popleft() # 从队列左侧取出节点(先进先出) vals.append(node.val) # 将节点值加入当前层列表 # 将子节点加入队列(下一层节点) if node.left: q.append(node.left) if node.right: q.append(node.right) # 将当前层的结果加入最终结果 ans.append(vals) return ans # 返回层序遍历结果 ``` ## 关键算法原理:广度优先搜索(BFS) 1. **队列的作用**: - 使用双端队列(`deque`)实现先进先出(FIFO)的队列 - 确保节点按层级顺序处理(先处理上层节点,再处理下层节点) 2. **核心循环逻辑**: ```python for _ in range(len(q)): # 当前层的节点数量 ``` - **关键技巧**:在开始处理当前层前,队列长度即为当前层的节点数 - 通过固定循环次数,确保每次只处理一层节点 3. **处理流程**: - 从队列取出节点 → 记录节点值 → 将子节点加入队列 - 完美实现层级递进:处理当前层时,同时准备下一层节点 ## 时间复杂度与空间复杂度 - **时间复杂度**:O(n) - 每个节点恰好入队和出队各一次 - 每个节点只被访问一次 - **空间复杂度**:O(n) - 队列最大空间需求为最宽层的节点数 - 最坏情况(完美二叉树)最后一层有 ⌈n/2⌉ 个节点 ## 示例执行流程 假设二叉树结构: ``` 3 / \ 9 20 / \ 15 7 ``` 执行步骤: 1. 初始队列:`[3]` 2. 处理第1层:vals=[3] → ans=[[3]] - 加入子节点后队列:`[9, 20]` 3. 处理第2层:vals=[9,20] → ans=[[3],[9,20]] - 加入子节点后队列:`[15,7]` 4. 处理第3层:vals=[15,7] → ans=[[3],[9,20],[15,7]] 5. 返回结果:`[[3],[9,20],[15,7]]` ## 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值