专题十四——BFS

目录

一BFS解决FloodFill算法

1图像渲染

2岛屿数量

3岛屿的最大面积 

4被环绕的区域

二BFS解决蛋源最短路径问题

1迷宫中离入口最近的出口

2最小基因变化

3单词接龙 

4为高尔夫比赛砍树

三BFS解决多源最短路径问题 

1 01矩阵

2飞地的数量

 3地图中的最高点

4地图分析


一BFS解决FloodFill算法

floodfill算法中文名:洪水灌溉:这类问题都是要来找出性质相同的联通块;解决好一道后,后面遇到类型的题目代码也是类似的!

1图像渲染

oj链接:图像渲染

解法:bfs

1.先把开始的坐标{sr,sc}放进队列中;

2.取出队头坐标{x,y},直接将它改成color(队列坐标都是合法的,待改的),再把它上下左右的坐标(等于image[sr][sc])放到队列中...

//dfs
class Solution
{
public:
    int target, newcolor, m, n;
    int dx[4] = {1, -1, 0, 0};
    int dy[4] = {0, 0, 1, -1};
    void dfs(vector<vector<int>> &image, int i, int j)
    {
        image[i][j] = newcolor;
        for (int a = 0; a < 4; a++)
        {
            int x = i + dx[a], y = j + dy[a];
            if (x >= 0 && x < m && y >= 0 && y < n && image[x][y] == target)
            {
                dfs(image, x, y);
            }
        }
    }

    vector<vector<int>> floodFill(vector<vector<int>> &image, int sr, int sc, int color)
    {
        if (image[sr][sc] == color)
            return image; // 特殊判断
        m = image.size(), n = image[0].size();
        target = image[sr][sc];
        newcolor = color;
        dfs(image, sr, sc);
        return image;
    }
};

//bfs
class Solution
{
public:
    vector<vector<int>> floodFill(vector<vector<int>> &image, int sr, int sc, int color)
    {
        if (image[sr][sc] == color)
            return image; // 特殊判断
        // bfs前准备
        int dx[4] = {1, -1, 0, 0};
        int dy[4] = {0, 0, 1, -1};
        int m = image.size(), n = image[0].size();
        int target = image[sr][sc];
        // bfs主逻辑
        queue<pair<int, int>> qe;
        qe.push({sr, sc});
        while (qe.size())
        {
            int sz = qe.size();
            for (int i = 0; i < sz; i++)
            {
                auto &[a, b] = qe.front();
                qe.pop();
                if (image[a][b] == target)
                    image[a][b] = color;
                for (int j = 0; j < 4; j++)
                {
                    int x = a + dx[j], y = b + dy[j];
                    if (x >= 0 && x < m && y >= 0 && y < n && image[x][y] == target)
                    {
                        qe.push({x, y});
                    }
                }
            }
        }
        return image;
    }
};

2岛屿数量

oj链接:岛屿数量

解法:bfs

1. 两层for循环找‘1’&&该位置没被标记,将该坐标进队列,执行一次bfs;

2.bfs的主逻辑与上题类似:但在这里要注意:坐标进队列后要立刻马上进行标记!如果是取出节点后标记的话,会有重复节点进队列导致超时!!

//dfs
class Solution
{
public:
    bool vis[300][300] = {false};
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int m, n;
    void dfs(vector<vector<char>> &grid, int i, int j)
    {
        vis[i][j] = true;
        for (int a = 0; a < 4; a++)
        {
            int x = i + dx[a], y = j + dy[a];
            if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] == '1')
            {
                dfs(grid, x, y);
            }
        }
    }
    int numIslands(vector<vector<char>> &grid)
    {
        m = grid.size(), n = grid[0].size();
        int ret = 0;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (grid[i][j] == '1' && !vis[i][j])
                {
                    ret++;
                    dfs(grid, i, j);
                }
            }
        }
        return ret;
    }
};

//bfs
class Solution
{
public:
    bool vis[300][300] = {false};
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int m, n;
    queue<pair<int, int>> q;

    void bfs(vector<vector<char>> &grid, int i, int j)
    {
        //进队列后必须立刻进行标记!
        q.push({i, j});
        vis[i][j] = true;
        while (q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            // vis[a][b]=true;节点会重复进队列,导致超时
            for (int k = 0; k < 4; k++)
            {
                int x = a + dx[k], y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1' && !vis[x][y])
                {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
    }
    int numIslands(vector<vector<char>> &grid)
    {
        m = grid.size(), n = grid[0].size();
        int ret = 0;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (grid[i][j] == '1' && !vis[i][j])
                {
                    ret++;
                    bfs(grid, i, j);
                }
            }
        }
        return ret;
    }
};

3岛屿的最大面积 

oj链接:岛屿的最大面积

与上题思路类似:只不过我们要求的是最大面积,我们可以:进行dfs后把岛屿的面积带出来

class Solution
{
public:
    int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, 1, -1};
    bool vis[50][50] = {false};
    int m, n;
    queue<pair<int, int>> q;
    void bfs(vector<vector<int>> &grid, int i, int j, int *area)
    {
        q.push({i, j});
        vis[i][j] = true;
        while (q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++)
            {
                int x = a + dx[k], y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y])
                {
                    q.push({x, y});
                    vis[x][y] = true;
                    (*area)++;
                }
            }
        }
    }
    int maxAreaOfIsland(vector<vector<int>> &grid)
    {
        m = grid.size(), n = grid[0].size();
        int MaxArea = 0;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (grid[i][j] == 1 && !vis[i][j])
                {
                    int area = 1; // 从该位置进行bfs:找出该位置处岛屿的面积
                    bfs(grid, i, j, &area);
                    MaxArea = max(MaxArea, area);
                }
            }
        }
        return MaxArea;
    }
};

4被环绕的区域

oj链接:被围绕的区域

解法:bfs

此题在递归 搜索与回溯算法题 

class Solution
{
public:
    bool vis[200][200];
    int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
    int m, n;
    queue<pair<int, int>> q;
    void bfs(vector<vector<char>> &board, int i, int j)
    {
        q.push({i, j});
        vis[i][j] = true;
        while (q.size())
        {
            auto [a, b] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++)
            {
                int x = a + dx[k], y = b + dy[k];
                if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O' && !vis[x][y])
                {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
    }

    void solve(vector<vector<char>> &board)
    {
        m = board.size(), n = board[0].size();
        for (int i = 0; i < m; i++)
        {
            if (board[i][0] == 'O')
                bfs(board, i, 0);
            if (board[i][n - 1] == 'O')
                bfs(board, i, n - 1);
        }
        for (int j = 0; j < n; j++)
        {
            if (board[0][j] == 'O')
                bfs(board, 0, j);
            if (board[m - 1][j] == 'O')
                bfs(board, m - 1, j);
        }
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (board[i][j] == 'O' && !vis[i][j])
                    board[i][j] = 'X';
            }
        }
    }
};

二BFS解决蛋源最短路径问题

1迷宫中离入口最近的出口

oj链接:迷宫中离入口最近的出口

从开始粗来一次bfs遍历即可;如果进队列的坐标是出口,直接返回遍历的层数ret即可!

class Solution
{
public:
    bool vis[100][100];
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int m, n;
    int nearestExit(vector<vector<char>> &maze, vector<int> &entrance)
    {
        m = maze.size(), n = maze[0].size();
        queue<pair<int, int>> q;
        int beginx = entrance[0], beginy = entrance[1];
        q.push({beginx, beginy});
        vis[beginx][beginy] = true;
        int ret = 0;
        while (q.size())
        {
            ret++; // 往外扩
            int sz = q.size();
            for (int i = 0; i < sz; i++)
            {
                auto [a, b] = q.front();
                q.pop();
                for (int k = 0; k < 4; k++)
                {
                    int x = a + dx[k], y = b + dy[k];
                    if (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == '.' &&!vis[x][y])
                    {
                        if (x == 0 || x == m - 1 || y == 0 || y == n - 1)
                            return ret; // 找到出口了,直接返回遍历的层数,即最短路径
                        q.push({x, y});
                        vis[x][y] = true;
                    }
                }
            }
        }
        return -1;
    }
};

2最小基因变化

oj链接:最小基因变化

class Solution
{
public:
    int minMutation(string startGene, string endGene, vector<string> &bank)
    {
        char arr[4] = {'A', 'G', 'C', 'T'};
        unordered_map<string, bool> vis;
        for (auto &s : bank)
            vis[s] = false;
        if(!vis.count(endGene)) return -1;// 不存在直接返回
        queue<string> q;
        q.push(startGene);
        vis[startGene] = true; // 有可能基因库也有这个,提前标记
        int ret = 0;
        while (q.size())
        {
            ret++;
            int sz = q.size();
            for (int i = 0; i < sz; i++)
            {
                string s = q.front();
                q.pop();
                for (int i = 0; i < 8; i++)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        string tmp = s;
                        tmp[i] = arr[j]; // 这里就没必要判断tmp[i]是否与arr[j]相等:因为前面我们已经标记过了
                        if (vis.count(tmp) && !vis[tmp])
                        {
                            if (tmp == endGene)
                                return ret;
                            q.push(tmp);
                            vis[tmp] = true;
                        }
                    }
                }
            }
        }
        return -1;
    }
};

3单词接龙 

oj链接:单词接龙

与上题思路类似 

class Solution
{
public:
    int ladderLength(string beginWord, string endWord, vector<string> &wordList)
    {
        string t = "qwertyuiopasdfghjklzxcvbnm";
        unordered_map<string, bool> vis;
        for (auto &word : wordList)
            vis[word] = false;
        if (!vis.count(endWord))
            return 0;

        int ans = 1;
        queue<string> qe;
        qe.push(beginWord);
        vis[beginWord] = true;
        while (qe.size())
        {
            ans++;
            int sz = qe.size();
            while (sz--)
            {
                string s = qe.front();
                qe.pop();
                for (int i = 0; i < s.size(); i++)
                {
                    char ch = s[i];
                    for (int j = 0; j < 26; j++)
                    {
                        s[i] = t[j];
                        if (vis.count(s) && !vis[s])
                        {
                            if (s == endWord)
                                return ans;
                            qe.push(s);
                            vis[s] = true;
                        }
                    }
                    s[i] = ch;
                }
            }
        }
        return 0;
    }
};

4为高尔夫比赛砍树

oj链接:为高尔夫比赛砍树

注意: 

不是说一定要砍,当初做的时候就是看劈叉了~

class Solution
{
public:
    typedef pair<int, int> PII;
    int n, m;
    int cutOffTree(vector<vector<int>> &forest)
    {
        // 先预处理砍树顺序
        vector<PII> trees;
        n = forest.size(), m = forest[0].size();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (forest[i][j] > 1)
                    trees.push_back({i, j});
            }
        }
        sort(trees.begin(), trees.end(), [&](const PII &p1, const PII &p2)
             { return forest[p1.first][p1.second] < forest[p2.first][p2.second]; });
        // 若干个迷宫问题的最小步数累加
        int dx = 0, dy = 0;
        int ret = 0;
        for (auto &[a, b] : trees)
        {
            int step = bfs(forest, dx, dy, a, b);
            if (step == -1)
                return -1;
            ret += step;
            dx = a, dy = b; // 更新位置
        }
        return ret;
    }
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int bfs(vector<vector<int>> &forest, int bx, int by, int ex, int ey)
    {
        if (bx == ex && by == ey)
            return 0;
        int step = 0;
        queue<PII> qe;
        bool vis[50][50] = {false};
        // 层序遍历主逻辑
        qe.push({bx, by});
        vis[bx][by] = true;
        while (qe.size())
        {
            step++;
            int size = qe.size();
            while (size--)
            {
                auto [a, b] = qe.front();
                qe.pop();
                for (int i = 0; i < 4; i++)
                {
                    int x = dx[i] + a, y = dy[i] + b;
                    if (x >= 0 && x < n && y >= 0 && y < m && !vis[x][y] && forest[x][y] != 0)
                    {
                        if (x == ex && y == ey)
                            return step;
                        vis[x][y] = true;
                        qe.push({x, y});
                    }
                }
            }
        }
        return -1;
    }
};

三BFS解决多源最短路径问题 

1 01矩阵

oj链接:01 矩阵

解法:BFS + 正难则反

如果从1作为起点走到终点0,那等到终点时记录距离时就不知道是从哪一个1为起点的

所以我们从0为起点开始,走到不是0的位置就进行距离记录,同时把它

class Solution
{
public:
    // bool vis[1000][1000];//开10000会溢出?
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int m, n;
    vector<vector<int>> updateMatrix(vector<vector<int>> &mat)
    {
        m = mat.size(), n = mat[0].size();
        vector<vector<int>> dist(m, vector<int>(n, -1));

        queue<pair<int, int>> q;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (mat[i][j] == 0)
                {
                    dist[i][j] = 0;
                    q.push({i, j});
                }
            }
        }
        // int step=0;
        while (q.size())
        {
            // step++;
            // int sz=q.size();
            // while(sz--)
            // {
            auto [a, b] = q.front();
            q.pop();
            for (int i = 0; i < 4; i++)
            {
                int x = dx[i] + a, y = dy[i] + b;
                // if(x>=0&&x<m&&y>=0&&y<n&&!vis[x][y])
                if (x >= 0 && x < m && y >= 0 && y < n && dist[x][y] == -1)
                {
                    // dist[x][y]=cnt;
                    // vis[x][y]=true;
                    dist[x][y] = dist[a][b] + 1;
                    q.push({x, y});
                }
            }
            // }
        }
        return dist;
    }
};

2飞地的数量

oj链接:飞地的数量

解法:dfs + 正难则反

a先把边界上的1进入队列并进行标记;

b进行dfs遍历(上下左右找合法坐标)只要它是1并且没被标记,就把它加入到队列中并进行标记;

c再次对grid进行遍历,只要坐标的值是1并且没别标记就代表它走不出边界,进行统计即可

class Solution
{
public:
    bool vis[500][500];
    int dx[4] = {0, 0, 1, -1}, dy[4] = {1, -1, 0, 0};
    int m, n;
    int numEnclaves(vector<vector<int>> &grid)
    {
        m = grid.size(), n = grid[0].size();
        queue<pair<int, int>> q;
        // 边上1统计
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (i == 0 || i == m - 1 || j == 0 || j == n - 1)
                {
                    if (grid[i][j] == 1)
                    {
                        q.push({i, j});
                        vis[i][j] = true;
                    }
                }
            }
        }
        // bfs进行遍历
        while (q.size())
        {
            // int sz=q.size();
            // while(sz--)
            // {
            auto [a, b] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++)
            {
                int x = dx[k] + a, y = dy[k] + b;
                if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y] && grid[x][y] == 1)
                {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
            // }
        }
        int ret = 0;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (!vis[i][j] && grid[i][j] == 1)
                    ret++;
            }
        }
        return ret;
    }
};

 3地图中的最高点

oj链接:地图中的最高点

解法:bfs

安排高度时,任意相邻的格子高度差至多为1,也就是既可以设计成0,也可以设计成1;

但题目要我们返回的是高度值最大的情况,所以我们贪心地把所有高度差都设计成1即可

也就是从所有水域位置为起点来来依次bfs遍历即可完成任务~

class Solution {
public:
    typedef pair<int,int> PII;
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    vector<vector<int>> highestPeak(vector<vector<int>>& isWater) 
    {
        queue<PII> qe;
        int n=isWater.size(),m=isWater[0].size();
        vector<vector<int>> hight(n,vector<int>(m,-1));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                if(isWater[i][j]==1)
                {
                    qe.push({i,j});
                    hight[i][j]=0;
                }
            }
        }
        while(qe.size())
        {
            int sz=qe.size();
            while(sz--)
            {
                auto[a,b]=qe.front();
                qe.pop();
                for(int i=0;i<4;i++)
                {
                    int x=dx[i]+a,y=dy[i]+b;
                    if(x>=0&&x<n&&y>=0&&y<m&&hight[x][y]==-1)
                    {
                        hight[x][y]=hight[a][b]+1;
                        qe.push({x,y});
                    }
                }
            }
        }
        return hight;
    }
};

4地图分析

oj链接:地图分析

 与01矩阵的思路一样~

//用dist数组
class Solution
{
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int maxDistance(vector<vector<int>> &grid)
    {
        int n = grid.size(), m = grid[0].size();
        vector<vector<int>> dist(n, vector<int>(m, -1));
        queue<PII> qe;
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (grid[i][j] == 1)
                {
                    qe.push({i, j});
                    dist[i][j] = 0;
                }
            }
        }
        if (qe.size() == 0 || qe.size() == n * m)
            return -1; // 边界情况
        int ans = 0;
        while (qe.size())
        {
            auto [a, b] = qe.front();
            qe.pop();
            for (int i = 0; i < 4; i++)
            {
                int x = dx[i] + a, y = dy[i] + b;
                if (x >= 0 && x < n && y >= 0 && y < m && dist[x][y] == -1)
                {
                    dist[x][y] = dist[a][b] + 1;
                    qe.push({x, y});
                    ans = max(ans, dist[x][y]);
                }
            }
        }
        return ans;
    }
};

//统计遍历层数
class Solution
{
public:
    bool vis[100][100];
    int dx[4] = {1, -1, 0, 0}, dy[4] = {0, 0, 1, -1};
    int m, n, ret = -1;
    int maxDistance(vector<vector<int>> &grid)
    {
        m = grid.size(), n = grid[0].size();
        queue<pair<int, int>> q;
        for (int i = 0; i < m; i++)
        {
            for (int j = 0; j < n; j++)
            {
                if (grid[i][j] == 1)
                {
                    q.push({i, j});
                    vis[i][j] = true;
                }
            }
        }
        if (q.size() == 0 || q.size() == m * n)
            return ret;

        while (q.size())
        {
            ret++;
            int sz = q.size();
            while (sz--)
            {
                auto [a, b] = q.front();
                q.pop();
                for (int i = 0; i < 4; i++)
                {
                    int x = a + dx[i], y = b + dy[i];
                    if (x >= 0 && x < m && y >= 0 && y < n && !vis[x][y])
                    {
                        q.push({x, y});
                        vis[x][y] = true;
                    }
                }
            }
        }
        return ret;
    }
};

四BFS解决拓扑排序

0拓扑排序简介

1课程表

oj链接:课程表

此题是拓扑排序的应用:判断有向图中是否有环

1 建图

根据数据量的稠密来选择用邻接矩阵还是邻接表(此题选择它)

2 代码如何建邻接表?

灵活使用STL中的容器:vector/hash 来储存每个点的边(出度)

用vector来储存每个点的入度情况

3进行拓扑排序

来一次BFS遍历即可!

class Solution
{
public:
    bool canFinish(int numCourses, vector<vector<int>> &prerequisites)
    {
        // vector建图
        vector<vector<int>> edge(numCourses);
        vector<int> in(numCourses);
        for (auto &p : prerequisites)
        {
            int a = p[0], b = p[1]; // b->a
            edge[b].push_back(a);
            in[a]++;
        }

        queue<int> q;
        // 入度为0存队列
        for (int i = 0; i < numCourses; i++)
        {
            if (in[i] == 0)
                q.push(i);
        }
        // BFS拓扑排序
        while (q.size())
        {
            int e = q.front();
            q.pop();
            // 该点指向的点的入度--
            for (auto &i : edge[e])
            {
                in[i]--;
                // 入度为0加队列
                if (in[i] == 0)
                    q.push(i);
            }
        }
        // 点对应的入度情况是否全为0
        for (auto &a : in)
        {
            if (a != 0)
                return false;
        }
        return true;
    }
};

2课程表Ⅱ

oj链接:课程表 II

与上题思路类似 

class Solution
{
public:
    vector<int> findOrder(int numCourses, vector<vector<int>> &prerequisites)
    {
        // hash建图
        unordered_map<int, vector<int>> edge;
        vector<int> in(numCourses);
        for (auto &p : prerequisites)
        {
            int a = p[0], b = p[1]; // b->a
            edge[b].push_back(a);
            in[a]++;
        }

        queue<int> q;
        // 入度为0存队列
        for (int i = 0; i < numCourses; i++)
        {
            if (in[i] == 0)
                q.push(i);
        }
        // BFS拓扑排序
        vector<int> ret;
        while (q.size())
        {
            int e = q.front();
            q.pop();
            ret.push_back(e);
            // 该点指向的点的入度--
            for (auto &i : edge[e])
            {
                in[i]--;
                // 入度为0加队列
                if (in[i] == 0)
                    q.push(i);
            }
        }
        // 是否是有环图
        for (auto &i : in)
        {
            if (i != 0)
                return {};
        }
        return ret;
    }
};

3火星词典

oj链接:火星词典

注意这种情况:

 

细节:

如果是words = {"ab","abc"}:则有合法顺序返回(此时abc随便一种顺序返回)

如果是words = {"abc","ab"}:这种情况是不合法的(s.length > t.length),返回“”

 

class Solution
{
public:
    // 用unordered_set去重方便
    unordered_map<char, unordered_set<char>> edges;
    // 用unordered_map统计方便
    unordered_map<char, int> in;
    // 标记非法情况
    bool check = false;

    void Add(string &s1, string &s2)
    {
        int n = min(s1.size(), s2.size());
        int i = 0;
        while (i < n && s1[i] == s2[i])
            i++;
        if ((i == s2.size() && i < s1.size()))
            check = true; // 解决这种{"abc","ab"}非法情况
        else if (i < s2.size() && i < s1.size())
        {
            char a = s1[i], b = s2[i]; // a->b
            if (!edges[a].count(b))
            {
                edges[a].insert(b);
                in[b]++;
            }
        }
    }

    string alienOrder(vector<string> &words)
    {
        int m = words.size();
        // 先进行初始化(后面入度为0才能统计)
        for (auto &s : words)
            for (auto &ch : s)
                in[ch] = 0;

        for (int i = 0; i < m; i++)
        {
            for (int j = i + 1; j < m; j++)
            {
                Add(words[i], words[j]);
                if (check)
                    return "";
            }
        }
        // 拓扑排序
        queue<char> q;
        string ret;
        for (auto &[ch, cnt] : in)
        {
            if (cnt == 0)
                q.push(ch);
        }
        while (q.size())
        {
            char ch = q.front();
            q.pop();
            ret += ch;

            for (auto &s : edges[ch])
            {
                in[s]--;
                if (in[s] == 0)
                    q.push(s);
            }
        }
        for (auto &[ch, cnt] : in)
        {
            if (cnt != 0)
                return "";
        }
        return ret;
    }
};

以上便是全部内容,有问题欢迎在评论区指出,感谢观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949587.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

openwrt 清缓存命令行

一、查看缓存 &#xff1a; free -m 二、清缓存&#xff1a;echo 3 > /proc/sys/vm/drop_caches  三、详解。 释放物理页缓存 echo 1 > /proc/sys/vm/drop_caches 释放可回收的slab对象&#xff0c;包含inode and dentry echo 2 > /proc/sys/vm/drop_caches 同时…

huggingface 下载方法 测试ok

目录 python下载方法&#xff1a; 设置环境变量 ~/.bashrc 缓存目录&#xff0c;默认模型下载目录 安装方法&#xff1a; python 下载无token&#xff1a; python 下载带token 常见报错 登录后创建Read token 2.3 创建token 使用token登录 python下载方法&#xff1…

滑动窗口_⻓度最⼩的⼦数组⽆重复字符的最⻓⼦串将x减到0的最⼩操作数

⻓度最⼩的⼦数组&#xff08;medium https://leetcode.cn/problems/minimum-size-subarray-sum/ 思路一&#xff1a;两个指针&#xff0c;p1 p2同时指向第一个元素。sump2,如果sum<target&#xff0c;p2直到大于&#xff0c;然后记录lenright-left。p1 p2再同时指向第二个…

【无标题】linux

Linux工具快速教程 Linux 基础 Linux工具快速教程1、使用命令帮助1.1 查看命令的简要说明1.2 查看路径 2. 文件及目录2.1 创建和删除2.2 切换目录2.3 列出目录项2.4 查找文件或目录 find2.5 查看文件内容2.6 查找文件内容 好用小工具linux工具电源统计1. 查询公网IPhttp://www.…

HarmonyOS-面试资料

1. HarmonyOS-面试资料 1.1. HarmonyOS 优点、特点 1.1.1. 优点 &#xff08;1&#xff09;在国家方面&#xff0c;是国产的系统&#xff0c;受国家支持不会有限制的情况。   &#xff08;2&#xff09;设备互连18N(1:手机 8&#xff1a;平板、PC、vr设备、可穿戴设备、智慧…

关于物联网的基础知识(一)

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于物联网的基础知识&#xff08;一&a…

基于Thinkphp6+uniapp的陪玩陪聊软件开发方案分析

使用uni-app框架进行前端开发。uni-app是一个使用Vue.js开发所有前端应用的框架&#xff0c;支持一次编写&#xff0c;多端发布&#xff0c;包括APP、小程序、H5等。 使用Thinkphp6框架进行后端开发。Thinkphp6是一个轻量级、高性能、面向对象的PHP开发框架&#xff0c;具有易…

springcloud 介绍

Spring Cloud是一个基于Spring Boot的微服务架构解决方案集合&#xff0c;它提供了一套完整的工具集&#xff0c;用于快速构建分布式系统。在Spring Cloud的架构中&#xff0c;服务被拆分为一系列小型、自治的微服务&#xff0c;每个服务运行在其独立的进程中&#xff0c;并通过…

jenkins入门6 --拉取代码

Jenkins代码拉取 需要的插件&#xff0c;缺少的安装下 新建一个item,选择freestyle project 源码管理配置如下&#xff1a;需要添加git库地址&#xff0c;和登录git的用户密码 配置好后执行编译&#xff0c;成功后拉取的代码在工作空间里

idea全局替换显示不全(ctrl+shift+R)

修改一下idea的配置就行 idea的默认显示条数为100&#xff0c;可以修改成10000

Ubuntu 下测试 NVME SSD 的读写速度

在 Ubuntu 系统下&#xff0c;测试 NVME SSD 的读写速度&#xff0c;有好多种方法&#xff0c;常用的有如下几种&#xff1a; 1. Gnome-disks Gnome-disks&#xff08;也称为“Disks”&#xff09;是 GNOME 桌面环境中的磁盘管理工具&#xff0c;有图形界面&#xff0c;是测试…

AI投资分析:用于股票评级的大型语言模型(LLMs)

“AI in Investment Analysis: LLMs for Equity Stock Ratings” 论文地址&#xff1a;https://arxiv.org/pdf/2411.00856 摘要 投资分析作为金融服务领域的重要组成部分&#xff0c;LLMs&#xff08;大型语言模型&#xff09;为股票评级带来了改进的潜力。传统的股票评级方式…

基于CLIP和DINOv2实现图像相似性方面的比较

概述 在人工智能领域&#xff0c;CLIP和DINOv2是计算机视觉领域的两大巨头。CLIP彻底改变了图像理解&#xff0c;而DINOv2为自监督学习带来了新的方法。 在本文中&#xff0c;我们将踏上一段旅程&#xff0c;揭示定义CLIP和DINOv2的优势和微妙之处。我们的目标是发现这些模型…

【学习笔记】数据结构(十)

内部排序 文章目录 内部排序10.1 概述10.2 插入排序10.2.1 直接插入排序10.2.2 其他插入排序10.2.2.1 折半插入排序(Binary Insertion Sort)10.2.2.2 2-路插入排序&#xff08;Two-Way Insertion Sort&#xff09;10.2.2.3 表插入排序&#xff08;Table Insertion Sort&#xf…

Unity学习笔记(七)使用状态机重构角色攻击

前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 攻击状态重构 首先我们重构攻击状态的动画 之前的动画&#xff0c;我们是使用状态(isAttacking)攻击次数(comboCounter)完成动画的过渡&#xff0c;这样虽然能完成功能&#xff0c;但是如…

Ubuntu20.04中安装ns-3.36及遇到的问题

一、安装虚拟机&#xff1a;VMware 17.5 参考教程&#xff1a;VMware17Pro虚拟机安装教程(超详细)-CSDN博客 博主&#xff1a;七维大脑 遇到的问题&#xff1a; Q1&#xff1a;安装ubuntu系统时&#xff0c;页面看不到”继续“选项&#xff0c;无法进行下一步 A&#xff…

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer

iOS 逆向学习 - iOS Architecture Cocoa Touch Layer 一、Cocoa Touch Layer 简介二、Cocoa Touch Layer 的核心功能1. UIKit2. Event Handling&#xff08;事件处理&#xff09;3. Multitasking&#xff08;多任务处理&#xff09;4. Push Notifications&#xff08;推送通知&…

人大金仓实现主键自增.

使用数据库中自带的参数类型 serial 类型(相当于创建一个INT列), 或者bigserial(相当于创建一个BIGINT列. 示例sql: CREATE TABLE ord(id SERIAL,ord_no INT NOT NULL,ord_name VARCHAR(32),CONSTRAINT "ord_PKEY" PRIMARY KEY ("id"));插入时指定自增值…

React Router 向路由组件传state参数浏览器回退历史页面显示效果问题

昨天在看尚硅谷张天禹老师讲的 React教程p90&#xff0c;老师讲到 React路由的 replace模式和push模式&#xff0c;老师的演示效果与自己本地操作不太一样。 老师的效果&#xff1a;点击查看消息1&#xff0c;消息2&#xff0c;消息3 再点回退&#xff0c;可以依次查看到 消息…

selenium无法定位元素的几种解决方案

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、frame/iframe表单嵌套 WebDriver只能在一个页面上对元素识别与定位&#xff0c;对于frame/iframe表单内嵌的页面元素无法直接定位。 解决方法&#xff1a; d…