《LeetCode 103 二叉树的锯齿形层序遍历 队列宽搜BFS解法》

一.题目

103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode)

二.思路讲解

2.1 思路讲解

锯齿形层序遍历 是在普通层序遍历的基础上,增加一个方向标志,用来控制每一层节点的输出顺序。

  • 核心思路 :使用队列进行层序遍历,同时维护一个布尔变量 flag(或 leftToRight),初始为 true 表示从左到右。

  • 每层处理 :记录当前层的节点数,依次取出节点,将节点值存入临时数组。若当前方向为从左到右,则直接存入;若为从右到左,则存入后需要反转该层的结果。

  • 方向切换 :每一层处理完毕后,将 flag 取反,即下一层的方向与当前层相反。

  • 结果收集:将每层处理后的数组依次加入最终结果集。

三.代码演示

cpp 复制代码
/**
 * 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) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root)
    {
        vector<vector<int>> ret;
        //如果为空
        if(root == nullptr) return ret;
        queue<TreeNode*> q;
        q.push(root);

        bool control = true;//标记位
        while(q.size())
        {
            int sz = q.size();
            vector<int> tmp;
            for(int i = 0;i < sz;i++)
            {
                TreeNode* t = q.front();//取出队头
                q.pop();//删除队头
                tmp.push_back(t->val);

                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            //为true不逆置,false逆置
            if(control == false)
            {
                reverse(tmp.begin(),tmp.end());
                control = true;
            }
            else
            {
                control = false;
            }
            ret.push_back(tmp);

        }
        return ret;     
    }
};

四.代码讲解

一、数据结构与初始化
  • ret:二维向量,存储最终的锯齿形层序遍历结果,每个子向量代表一层的节点值。

  • q:队列,用于按层顺序暂存待处理的节点。队列的先进先出特性保证了同层节点从左到右的顺序(但后续通过反转实现锯齿形)。

  • control :布尔变量,标记当前层是否需要反转。初始为 true,表示第一层从左到右(不反转);后续每处理完一层后切换。

二、边界处理

如果根节点 root 为空,直接返回空结果集 ret

三、主循环:逐层处理

当队列不为空时,表示还有节点未处理,继续循环。

1. 记录当前层节点数

复制代码
int sz = q.size();

此时队列中存放的恰好是当前层的所有节点(上一层的子节点已全部入队),sz 即为本层节点个数。

2. 处理当前层节点

创建一个临时向量 tmp 用于存放本层的节点值。 循环 sz 次:

  • 取出队头节点 t,并将其值加入 tmp

  • t 的左子节点和右子节点(若存在)依次入队,保证下一层节点按从左到右的顺序进入队列。

3. 根据方向决定是否反转

  • 如果 control == false,说明当前层应该从右到左输出,因此将 tmp 反转。

  • 反转后,将 control 置为 true,表示下一层方向变回从左到右。

  • 如果 control == true,则当前层不反转,直接将 control 置为 false,表示下一层需要反转。

4. 存储本层结果

将处理后的 tmp 加入 ret

四、关键细节
  • 方向交替 :通过 controltruefalse 之间来回切换,实现了锯齿形遍历。

  • 反转时机:只有在需要从右到左输出的层才反转临时数组,反转后立即切换标志,确保下一层方向正确。

  • 队列长度固定 :在进入内层循环前先记录 sz,确保只处理当前层的节点,避免将下一层节点提前混入。

五、流程图