C++算法:队列与BFS

队列与BFS

1.N叉树的层序遍历

使用BFS,即宽度优先搜索。把节点放入队列中,当节点出队列时让其孩子节点入队列,记录每层节点数量。

cpp 复制代码
class Solution {
public:
    vector<vector<int>> levelOrder(Node* root)
    {
        vector<vector<int>> ret;
        queue<Node*> q;
        if (root == nullptr)
            return ret;
        q.push(root);
        while (!q.empty())
        {
            vector<int> v;
            int len = q.size(); //当前层节点数量
            for (int i = 0;i < len;i++)
            {
                Node* p = q.front();
                q.pop();
                v.push_back(p->val);

                for (Node* child : p->children)//下一层节点入队列
                    if (child != nullptr)
                        q.push(child);
            }
            ret.push_back(v);
        }
        return ret;
    }
};

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

与上一题相似,锯齿形层序遍历时,可以照常从左到右遍历,把第一层记为level=1,每偶数层时逆序数组即可。也可以使用别的方法,只要能在偶数层逆序即可。

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;
        queue<TreeNode*> q;
        int flag = 1;  // 规定flag<0小于时逆序数组。
        if (root == nullptr)
            return ret;
        q.push(root);
        while (!q.empty())
        {
            int len = q.size();
            vector<int> v;
            for (int i = 0;i < len;i++)
            {
                TreeNode* p = q.front();
                q.pop();
                v.push_back(p->val);

                if (p->left)
                    q.push(p->left);
                if (p->right)
                    q.push(p->right);
            }
            if (flag < 0) //判断是否逆序数组
                reverse(v.begin(), v.end());
            flag *= -1;
            ret.push_back(v);
        }
        return ret;
    }
};

3.二叉树最大宽度

根据题意,如果直接按照前面题目的模板,会出现超出内存限制的情况。如下图所示,3000个节点分别位于两侧,中间全为空节点。

此时可以考虑树的顺序存储。即给树的每个节点从左到右,从上到下编号,如果从1开始编号,某个节点下标为x,则它的孩子节点为2x和2x+1。依旧使用循环+队列的模板,非空节点入队列,队列元素应使用pair类型,记录节点及其下标,每次循环取队头和队尾的下标做差再加1,即可求出一层的宽度。

题目保证最终的宽度在32位带符号的整数范围内,如果用int做差返回的宽度错误,用unsigned int则能够正确返回宽度。

cpp 复制代码
class Solution {
public:
    int widthOfBinaryTree(TreeNode* root)
    {
        queue<pair<TreeNode*, unsigned int>> q;
        unsigned int ret = 0;
        q.push({ root,1 });
        while (!q.empty())
        {
            auto e1 = q.front();
            auto e2 = q.back();
            ret = max(ret, e2.second - e1.second + 1);
            size_t len = q.size();
            for (int i = 0;i < len;i++)
            {
                auto p = q.front();
                q.pop();
                if (p.first->left)
                    q.push({ p.first->left,p.second * 2 });
                if (p.first->right)
                    q.push({ p.first->right,p.second * 2 + 1 });
            }
        }
        return ret;
    }
};

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

与1、2题类似。只需用一个变量在遍历时记录最大值即可。

cpp 复制代码
class Solution {
public:
    vector<int> largestValues(TreeNode* root)
    {
        queue<TreeNode*> q;
        vector<int> ret;
        if (root == nullptr)
            return ret;
        q.push(root);
        while (!q.empty())
        {
            int Max = INT_MIN;
            size_t len = q.size();
            for (int i = 0;i < len;i++)
            {
                TreeNode* p = q.front();
                q.pop();
                if (Max < p->val)
                    Max = p->val;

                if (p->left)
                    q.push(p->left);
                if (p->right)
                    q.push(p->right);
            }
            ret.push_back(Max);
        }
        return ret;
    }
};
相关推荐
aaPIXa6222 小时前
C++模板元编程:在编译期完成计算,实现零运行时开销
java·开发语言·c++
Ivanqhz2 小时前
注意力机制
线性代数·算法·矩阵·哈希算法·dnn
z小猫不吃鱼2 小时前
02 Optimal Brain Damage 详解:二阶信息剪枝的起点
算法·机器学习·剪枝
Keven_112 小时前
算法札记:如何判断一个DP能否单调队列优化
算法
m0_626535202 小时前
近似attention
人工智能·算法·机器学习
郝学胜-神的一滴2 小时前
CMake 038:OBJECT目标复用编译+Linux动态库版本自动化管理
linux·c++·程序人生·软件工程·软件构建·cmake·工程配置
atunet2 小时前
关于算法优化的渐进式重构与代码级实践的技术7
算法
Sylvia-girl3 小时前
第八站:vector及其常用操作【上】
c++
霖大侠3 小时前
Decoupled and Reusable Adaptation for Efficient Cross-Modal Transfer
人工智能·深度学习·算法·机器学习·transformer