BinaryTree 层序遍历 LC.102

#binaryTree #cpp

102. 二叉树的层序遍历

题目地址:102. 二叉树的层序遍历

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

示例 1:

img

输入: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

这里是题目给出的二叉树定义

/**
 * 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) {}
 * };
 */

在此我们先不去管题目的输出要求,我们来讲一下如何去用队列实现二叉树的层序遍历。

什么是层序遍历

层序遍历就是按照从顶至底的方式,按照一定的顺序将处于同一树层的元素全部访问的过程。

核心思想算法

​ 从图中我们可以看出,每次只有遍历完当前层的所有节点后,才到下一层进行遍历,像这种从一个节点开始,像辐射一样把所有可行的路径探索后才访问下一层的访问方式叫做广度优先搜索(Breadth-first search)简称BFS

BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

  1. 使用队列来存储每一层的节点。

  2. 从根节点开始,将其加入队列。

  3. 当队列非空时,执行以下步骤:

    • 获取当前队列的大小(即当前层的节点数)。

    • 遍历当前层的所有节点:

      • 将节点从队列中取出。
        • 将该节点的值加入结果。
        • 如果该节点有左子节点,将左子节点加入队列。
        • 如果该节点有右子节点,将右子节点加入队列。
queue_tree3 queue_tree3 queue_tree3
queue_tree3 queue_tree3

其中能保证按照有序按层输出的主要是因为我们将节点访问顺序依次加入了队列,在每次弹出时又仅仅将下一层的节点加入,我们可以写出如下代码。

vector<int> levelOrderTraversal(BinaryTree* root){
        queue<BinaryTree*> q;
        int size = 0;
        vector<int> visited;
        
        if(root == nullptr) return visited; //若树为空,直接返回.
            q.push(root);
      
            while(!q.empty()){ //若队列为空,此时已全部访问
                    BinaryTree* temp = q.front();  
                    q.pop(); //弹出首元素
                    visited.push_back(temp->val); //装入visited
                    if(temp->left != nullptr) q.push(temp->left); //若节点不为空,将节点加入待访问队列
                    if(temp->right != nullptr) q.push(temp->right);
                	
                }
        
        return visited;
    }

题解

BFS队列实现

掌握了基本了的思想,我们现在回到题目。 题目要求我们返回的是一个二维数组,也就是对在同一层的节点值进行分层,我们需要对每层的节点数做单独的记录,当计数器为零时,将数组中的元素加到res数组中。

while(!q.empty()){
            int size = q.size(); //每次记录当前层内节点数
            vector<int> visited;
            while(size > 0){ //只有当前层全部访问完之后 才将结果加入res
                auto tmp = q.front();
                visited.push_back(tmp->val);
                q.pop();
                if(tmp != nullptr && tmp->left != nullptr) q.push(tmp->left);
                if(tmp != nullptr && tmp->right != nullptr) q.push(tmp->right);
                size--;
            }
            res.push_back(visited);
        }

DFS递归实现

这是使用队列的解法,我们也可以使用递归进行求解,这里只简单介绍思路。

调用DFS函数将本节点元素加入res数组对应层数depth,然后递归调用传入左右节点,增加层数depth+1,如此即使访问顺序虽然是深度优先,但依然能正确传入对应层数。

void dfs(TreeNode* node, int depth, vector<vector<int>>& res) {
        if (!node) return;
        
        if (depth >= res.size()) {
            res.push_back(vector<int>());
        }
        
        res[depth].push_back(node->val);
        
        dfs(node->left, depth + 1, res);
        dfs(node->right, depth + 1, res);
    }