优选算法——队列+宽搜

💁‍♂️个人主页:进击的荆棘

👇作者其它专栏:

《数据结构与算法》《算法》《C++起始之路》


相关题解

1.N 叉树的层序遍历

算法思路:

层序遍历即可,仅需多加一个变量,用来记录每一层节点的个数。

cpp 复制代码
/*
// Definition for a Node.
class Node {
public:
    int val;
    vector<Node*> children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector<Node*> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> ret;
        if(!root) return ret;
        queue<Node*> q;
        q.push(root);
        int n=0;//存当前队列中有多少数据(即每一层有多少数据)
        while(!q.empty()){
            vector<int> t;
            n=q.size();
            while(n--){//压入当前层的数据
                t.push_back(q.front()->val);
                //将下层节点存入队列中
                for(int i=0;i<q.front()->children.size();i++){
                    q.push(q.front()->children[i]);
                }
                q.pop();
            }
            ret.push_back(t);
        }
        return ret;
    }
};

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

算法思路:

在正常的层序遍历过程中,可以把一层的节点放在一个数组中,有了这个数组后,在合适的层数逆序就可以得到锯齿形层序遍历的结果。

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) return ret;
        queue<TreeNode*> q;
        int n=0;
        q.push(root);
        int flag=1;
        while(!q.empty()){
            vector<int> t;
            n=q.size();
            while(n--){
                t.push_back(q.front()->val);
                if(q.front()->left) q.push(q.front()->left);
                if(q.front()->right) q.push(q.front()->right);
                q.pop();
            }
            //判断是否逆序
            if(flag%2==0) reverse(t.begin(),t.end());
            ret.push_back(t);
            flag++;
        }
        return ret;
    }
};

3.二叉树最大宽度

算法思路一(会超过内存限制):

既然统计每一层的最大宽度,优先想到的就是利用层序遍历,把当前层的节点全部存在队列里,利用队列的长度来计算每一层的宽度,统计出最大的宽度。

但是,由于空节点也是需要计算在内的。因此,可以选择将空节点也存在队列里。

但是极端情况下,最左边一条长链,最右边一条长链,会超出最大内存限制。

算法思路二:(利用二叉树的顺序存储,通过根节点的下标,计算左右孩子的下标):

还是利用层序遍历,但是这一次队列里面不只是存节点信息,并且还存储当前节点对应存在数组中的下标(用数组实现堆时,计算左右孩子的方式)。

这样计算每一层宽度时,无需考虑空节点,只需将当前节点的左右节点的下标相减在加1即可。

细节:若二叉树的层数非常恐怖的话,任何一种数据类型都不能存下下标的值。但是没有问题,因为:

●数据的存储是一个环形的结构;

●且题目说明,数据的范围在int类型的最大值的范围之内,因此不会超出一圈;

●因此,若是求差值,无需考虑溢出的情况。

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:
    //思考用数组模拟堆时的下标之间的关系
    int widthOfBinaryTree(TreeNode* root) {
        vector<pair<TreeNode*,unsigned int>> q;//用数组模拟队列
        q.push_back({root,1});
        unsigned int ret=1;
        while(q.size()){
            auto& [x1,y1]=q[0];
            auto& [x2,y2]=q.back();
            ret=max(ret,y2-y1+1);
            //模拟队列进队
            vector<pair<TreeNode*,unsigned int>> t;//频繁在q头删除元素,时间消耗大,可以用一个数组直接覆盖
            for(auto& [x,y]:q){
                if(x->left) t.push_back({x->left,y*2});
                if(x->right) t.push_back({x->right,y*2+1});
            }
            q=t;
        }
        return ret;
    }
};

4.在每个树行中找最大值

算法思路:

层序遍历过程中,在执行让下一层节点入队时,可以在循环中统计出当前层节点的最大值。

因此,可以在bfs的过程中,统计出每一层节点的最大值。

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<int> largestValues(TreeNode* root) {
        vector<int> ret;
        if(!root) return ret;
        queue<TreeNode*> q;
        q.push(root);
        int n=0;
        while(q.size()){
            n=q.size();
            int t=INT_MIN;
            while(n--){
                if(q.front()->left) {
                    q.push(q.front()->left);
                }
                if(q.front()->right) {
                    q.push(q.front()->right);
                }
                t=max(q.front()->val,t);
                q.pop();
            }
            ret.push_back(t);
        }
        return ret;
    }
};
相关推荐
Hall_IC1 小时前
LSM6DS3TR-C现货询价丨粤科源兴ST代理商,专业FAE技术支持
c++
填满你的记忆1 小时前
《动态规划-基础篇》
算法·动态规划·力扣
Irissgwe1 小时前
STL简介
c++·stl
黎阳之光1 小时前
虚实同源·数智治水:黎阳之光视频孪生,重构智慧水务新范式
运维·物联网·算法·安全·数字孪生
江屿风1 小时前
C++OJ题经验总结(竞赛)4
开发语言·c++·笔记·算法·dp·双指针
Deep-w1 小时前
【MATLAB】微电网四DG逆变器下垂策略与分布式MPC协同控制仿真分析
开发语言·分布式·算法·matlab
码上有光1 小时前
c++: 继承(下)
android·java·c++·多继承·菱形继承·虚继承
手写码匠1 小时前
华为云Flexus+DeepSeek征文|万字实战:MaaS 推理服务 + Dify 高可用部署 + AI Agent 开发全流程
人工智能·深度学习·算法·aigc
yu85939581 小时前
基于卡尔曼滤波器的集中式机器人轨迹定位算法
算法·机器人