13.二叉树 层序遍历

126 阅读2分钟

灵神【基础算法精讲】视频的个人笔记。

层序遍历:从上往下,从左往右遍历。

视频例题

102. 二叉树的层序遍历

image.png

可以用两个数组,一个存当前层数的节点,另一个存下一层的节点。

队列实现更加方便。

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if(!root) return {};

        vector<vector<int>> ans;
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty()) {
            vector<int> vals; //一层的值
            int len = q.size();

            for (int i = 0; i < len; ++i) { //遍历当前层
                TreeNode* t = q.front();
                q.pop();
                vals.emplace_back(t->val);

                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            ans.emplace_back(vals);
        }

        return ans;
    }
};

103. 二叉树的锯齿形层序遍历

image.png

思路: 这题在层序遍历的基础上,多了一个条件:交替进行正序倒序。 那就需要一个标记,是否需要倒序

  • 需要就逆转该层的vals数组
  • 否则不变
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(!root) return {};

        vector<vector<int>> ans;
        int flag = false; //是否需要倒序
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty()) {
            vector<int> vals;
            int len = q.size();

            for (int i = 0; i < len; ++i) {
                TreeNode* t = q.front();
                q.pop();
                vals.emplace_back(t->val);

                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            if(flag)
                reverse(vals.begin(), vals.end()); //倒序

            ans.emplace_back(vals);
            flag = !flag;
        }

        return ans;
    }
};

513. 找树左下角的值

image.png

思路: 按照层序遍历的顺序,从左到右,最后一个节点就是最底层最右边的节点。 如果反过来,从右到左层序遍历,那么最后一个节点就是最底层最左边的节点了。

由于不需要每一层的值,就不需要for (int i = 0; i < len; ++i)来遍历当前层,直接去掉。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        if(!root) return 0;

        queue<TreeNode*> q;
        q.push(root);
        TreeNode* t;

        while(!q.empty()) {
            t = q.front();
            q.pop();

            if(t->right) q.push(t->right);
            if(t->left) q.push(t->left);
        }
        return t->val; //最后一个节点
    }
};

课后作业

104. 二叉树的最大深度

image.png

思路: 遍历完一层,深度+1

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if(!root) return 0;

        queue<TreeNode*> q;
        q.push(root);
        int depth = 0;

        while(!q.empty()) {
            int len = q.size();
            for (int i = 0; i < len; ++i) { //遍历当前层
                TreeNode* t = q.front();
                q.pop();
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            depth++;
        }

        return depth;
    }
};

111. 二叉树的最小深度

image.png

思路: 层序遍历是从上往下,遇到的第一个叶子节点肯定是深度最小的。

每一个节点都判断是否叶子节点,是就直接返回。

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(!root) return 0;

        queue<TreeNode*> q;
        q.push(root);
        int cnt = 0; //层数

        while(!q.empty()) {
            int len = q.size();
            cnt++;
            for (int i = 0; i < len; ++i) {
                auto t  = q.front();
                q.pop();

                if(t->left == nullptr && t->right == nullptr) //叶子节点,直接返回
                    return cnt;

                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
        }
        return 0;
    }
};

199.二叉树的右视图

image.png

思路: 每一层只要最后一个节点。

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        if(!root) return {};

        vector<int> ans;
        queue<TreeNode*> q;
        q.push(root);

        while(!q.empty()) {
            int len = q.size();
            TreeNode* t;
            for (int i = 0; i < len; ++i) {
                t  = q.front();
                q.pop();

                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }

            ans.emplace_back(t->val); //该层最后一个节点
        }

        return ans;
    }
};