C++刷题笔记(18)——二叉树的层序遍历、leetcode102、107、199、637、429、515

二叉树的层序遍历

层序遍历就是从上到下、从左到右的遍历二叉树,可以借助队列来实现。

队列先进先出,符合一层一层遍历的逻辑。

题目1:102.二叉树的层序遍历(模板)

在这里插入图片描述
解题思路:
从上到下,那么就首先将根节点入队,其实也就是将第一层入队,这里要进行一个判空,如果队列不为空,那么就将队列里的元素放入数组中,然后进行下一层的拓展,直到队列为空。
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {       //传入的数据为二叉树头节点指针
        queue<TreeNode*> que;                              //用队列存储节点的指针,实现层序遍历
        vector<vector<int>> result;                        //用一个二元组(node,level)表示状态,将同一层的放在一起
        if (root != NULL) que.push(root);                  //判断是否为空,不为空首先将根节点入队
        while (!que.empty()) {                             
            int size = que.size();                         //求当前队列的长度s
            vector<int> vec;                               //用vec存储每一层
            for (int i = 0; i < size; i++) {               //依次从队列中取s个元素入队(即每一层)
                TreeNode* node = que.front();              //获取第一个节点数据
                que.pop();                                
                vec.push_back(node->val);                  //将队列中的元素存入数组中
                if (node->left) que.push(node->left);      //将当前层的下一层节点入队
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);                         //将一层的数据保存
        }
        return result;
    }
};

这份代码也可以作为二叉树层序遍历的模板

题目2:107.二叉树的层次遍历II

在这里插入图片描述
解题思路:
102是从上到下,这一题要求自底向上。其实还是可以套用102的模板,只需要将最后的result反转。

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*>que;
        vector<vector<int>> result;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            vector<int>vec;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        reverse(result.begin(), result.end());     //反转结果数组
        return result;
    }
};

题目3:199.二叉树的右视图

在这里插入图片描述

解法一:广度优先搜索

解题思路:
这题刚开始被示例误导了,以为只要去掉node->right就可以,但是仔细一想,左子树可以比右子树长,只要不被右子树遮挡,在右侧依然能够看到。

但是依然可以套用102的模板,利用广度优先搜索进行层次遍历,每遍历一层就记下该层最后一个元素(下图红色)
在这里插入图片描述

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*>que;
        vector<int> result;                                       //根据返回值确定放入result的数据类型
        if (root != NULL) que.push(root); 
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                if (i == (size - 1)) result.push_back(node->val); //将每一层的最后元素放入result数组中
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
        }
        return result;
    }
};

解法二:深度优先搜索

解题思路:
在深度优先搜索中,并不一定要拘泥于前中后序遍历三种形式,比如这一题,如果按照 根节点->右子树->左子树的顺序遍历二叉树,那么在遍历过程中每层都是最先访问最右边的节点
在这里插入图片描述

class Solution {
public:
    vector<int> result;
    void DFS(TreeNode* root, int depth) {
        if (root == NULL) return;
        if (depth == result.size()) {
            result.push_back(root->val);
        }
        depth++;
        DFS(root->right, depth);
        DFS(root->left, depth);
    }

    vector<int> rightSideView(TreeNode* root) {
        DFS(root, 0);
        return result;
    }
};

题目4:637.二叉树的层平均值

在这里插入图片描述

解法一:广度优先搜索

每一层节点的平均值,那么就可以用BFS进行遍历然后求和求平均值

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {  
        queue<TreeNode*> que;        
        vector<double> result; 
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();                
            double sum = 0;
            for (int i = 0; i < size; i++) {   
                TreeNode* node = que.front(); 
                que.pop();
                sum += node->val;            //每一轮遍历都会将队列中的节点全部取出,计算其和
                if (node->left) que.push(node->left); 
                if (node->right) que.push(node->right);
            }


            result.push_back(sum / size);    //将一层的数据保存
        }
        return result;
    }
};

解法二:深度优先搜索

DFS就比较麻烦了,要用两个数组,一个存储二叉树的每一层节点数,另外一个存储二叉树每一层节点的和,然后在数组中计算每层节点的和。

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        vector<int> counts;                            //存储二叉树的每一层节点数
        vector<double> sums;                           //存储二叉树每一层节点的和
        vector<double> result;
        dfs(root, 0, counts, sums);                    //从第0层的根节点开始
        int size = sums.size();                        //这句不能写在dfs前面
        for (int i = 0; i < size; i++) {
            result.push_back(sums[i] / counts[i]);
        }
        return result;
    }

    void dfs(TreeNode* root, int i, vector<int>& counts, vector<double>& sums) {
        if (root == NULL) return;
        if (i < sums.size()) {      //访问到的节点在第i层
            sums[i] += root->val;
            counts[i] += 1;
        }
        else {                          //访问到的节点在别的层,就在数组中尾部添加一个节点值和节点个数
            sums.push_back(root->val);
            counts.push_back(1);
        }
        dfs(root->left, i + 1, counts, sums);
        dfs(root->right, i + 1, counts, sums);
    }
};

题目5:429.N叉树的层序遍历

在这里插入图片描述
解题思路:
从二叉树变成了N叉树,那么只需要修改二叉树向左右子树遍历的方式即可

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        queue<Node*> que;
        vector<vector<int>> result;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();                                     //N叉树当前层节点个数
            vector<int> vec;
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                vec.push_back(node->val);
                for (int i = 0; i < node->children.size(); i++) {        //将下一层的非空节点入队
                    if (node->children[i]) que.push(node->children[i]); 
                }
            }
            result.push_back(vec);
        }
        return result;

    }
};

题目6:515.在每个树行中找最大值

在这里插入图片描述
层序遍历,将每一行的最大值添加进数组

class Solution {
public:
    vector<int>largestValues(TreeNode* root) {
        queue<TreeNode*> que;
        vector<int> result;
        if (root != NULL) que.push(root);
        while (!que.empty()) {
            int size = que.size();
            int maxvalue = INT_MIN;
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                maxvalue = node->val > maxvalue ? node->val : maxvalue;
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(maxvalue);
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值