我爱学算法之—— BFS之FLoodFill算法

前言

FloodFill是一直从指定起点出发,通过递归/迭代遍历相邻且满足条件的算法。

核心原理

  • 以起始位置为中心,向上下左右等相邻方向扩散。
  • 只遍历与起始点相邻且满足条件的元素,遇到边界(属性不同)则停止。

这里使用BFS算法,来解决这类问题。

BFS也就是广度优先遍历,代码实现通常要使用队列结构,类似与层序遍历的操作。

一、图像渲染

题目解析

这道题给定一个n*m的二维数组,以及起点坐标(sr,sc),以及要修改的颜色color,我们要从(sr,sc)开始对其相邻(上、下、左、右)且与该位置颜色相同(对应位置的值相等)进行染色。

最后返回染色号的数组。

算法思路

这道题还是非常简单的,我们只需要从(sr,sc)开始,进行一次BFS,在遍历的过程中进行染色即可。

这道题也可以使用DFS、递归遍历来解决。

代码实现

cpp 复制代码
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>> floodFill(vector<vector<int>>& image, int sr, int sc,
                                  int color) {
        int prev = image[sr][sc];
        if (prev == color)
            return image;
        int n = image.size();
        int m = image[0].size();
        queue<PII> pq;

        pq.push({sr, sc});
        while (pq.size() > 0) {
            auto [x, y] = pq.front();
            pq.pop();
            image[x][y] = color;
            for (int i = 0; i < 4; i++) {
                int a = x + dx[i];
                int b = y + dy[i];
                if (a >= 0 && a < n && b >= 0 && b < m && image[a][b] == prev)
                    pq.push({a, b});
            }
        }
        return image;
    }
};

二、岛屿数量

题目解析

给定一个n*m的二维数组,其中1表示陆地、0表示海洋;

多个相邻的陆地可以看做是一座岛屿,要求计算网格中岛屿的数量。

算法思路

这道题也是一道典型的BFS/DFS的题目了,整体思路:

遍历grid数组,遍历到陆地(1)并且该陆地没有和其他陆地形成岛屿(没有被BFS/DFS遍历过),就从该节点进行一次BFS/DFS遍历。

这样我们只需要统计在遍历grid时,进行BFS/DFS的次数即可。

这里使用BFS来解决这道题问题。

代码实现

cpp 复制代码
class Solution {
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    bool vis[310][310] = {false};
    int numIslands(vector<vector<char>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        int ret = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == '1' && vis[i][j] == false) {
                    ret++;
                    bfs(grid, i, j);
                }
            }
        }
        return ret;
    }
    void bfs(vector<vector<char>>& grid, int i, int j) {
        // bfs遍历
        int n = grid.size();
        int m = grid[0].size();
        queue<PII> q;
        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];
                int y = b + dy[k];
                if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == '1' &&
                    vis[x][y] == false) {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
    }
};

三、岛屿的最大面积

题目解析

这道题和求岛屿数量可以说是大同小异,这道题要求我们求出岛屿的最大面积。

算法思路

这道题的结题思路也是和求岛屿数量大同小异;

还是遍历grid数组,在遍历到陆地并且该陆地没有和其他陆地组成岛屿。(遍历到1并且该位置没有被遍历过)

就从该位置进行一次BFS遍历(DFS也可以解决),并求出岛屿的面积;

然后统计岛屿面积的最大值然后返回即可。

代码实现

cpp 复制代码
class Solution {
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    int vis[55][55] = {false};
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        int n = grid.size();
        int m = grid[0].size();
        int ret = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (grid[i][j] == 1 && vis[i][j] == false) {
                    int tmp = bfs(grid, i, j);
                    ret = max(ret, tmp);
                }
            }
        }
        return ret;
    }
    int bfs(vector<vector<int>>& grid, int i, int j) {
        int n = grid.size();
        int m = grid[0].size();
        queue<PII> q;
        q.push({i, j});
        vis[i][j] = true;
        int ret = 1;
        while (q.size()) {
            auto [a, b] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++) {
                int x = a + dx[k];
                int y = b + dy[k];
                if (x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == 1 &&
                    vis[x][y] == false) {
                    q.push({x, y});
                    vis[x][y] = true;
                    ret++;
                }
            }
        }
        return ret;
    }
};

四、被围绕的区域

题目解析

这道题给定一个字符矩阵board,其中只包含XO

题目要求捕获所有被围绕的区域:一块相邻且都是O的区域,如果它不在边缘,就全部修改成X

算法思路

简单来说,这道题就是让我们将一块相邻且都是O,并且不在边缘的区域全部修改成X

这里如果直接去解决这个问题,还是有一点难度的(有进行BFS遍历时,还要判断它是否在边缘,不在边缘才能修改)。

直接去修改不行,那我们是不是可以先将在边缘的O区域进行标记(特殊处理);

然后再将没有标记的所有O都修改成X

最后,复原位于边缘的O区域。

这里可以创建一个等大的二维数组,来标记是否位于边缘;也可以先将位于边缘的O区域修改成不相干的字符,最后再复原即可。

代码实现

cpp 复制代码
class Solution {
public:
    typedef pair<int, int> PII;
    int dx[4] = {0, 0, 1, -1};
    int dy[4] = {1, -1, 0, 0};
    // bfs
    void bfs(vector<vector<char>>& board, vector<vector<bool>>& vis, int i,
             int j) {
        vis[i][j] = true;
        int n = board.size();
        int m = board[0].size();
        queue<PII> q;
        q.push({i, j});
        while (q.size() > 0) {
            auto [a, b] = q.front();
            q.pop();
            for (int k = 0; k < 4; k++) {
                int x = a + dx[k];
                int y = b + dy[k];
                if (x >= 0 && x < n && y >= 0 && y < m && board[x][y] == 'O' &&
                    vis[x][y] == false) {
                    q.push({x, y});
                    vis[x][y] = true;
                }
            }
        }
    }
    void solve(vector<vector<char>>& board) {
        // 遍历四周的'o'
        int n = board.size();
        int m = board[0].size();
        vector<vector<bool>> vis(n, vector<bool>(m, false));
        for (int i = 0; i < m; i++) {
            if (board[0][i] == 'O' && vis[0][i] == false)
                bfs(board, vis, 0, i);
            if (board[n - 1][i] == 'O' && vis[n - 1][i] == false)
                bfs(board, vis, n - 1, i);
        }
        for (int i = 0; i < n; i++) {
            if (board[i][0] == 'O' && vis[i][0] == false)
                bfs(board, vis, i, 0);
            if (board[i][m - 1] == 'O' && vis[i][m - 1] == false)
                bfs(board, vis, i, m - 1);
        }
        for (int i = 1; i < n - 1; i++) {
            for (int j = 1; j < m - 1; j++) {
                if (board[i][j] == 'O' && vis[i][j] == false)
                    board[i][j] = 'X';
            }
        }
    }
};

本篇文章到这里就结束了,感谢支持

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

相关推荐
信奥卷王1 小时前
2025年9月GESPC++三级真题解析(含视频)
开发语言·c++·算法
天选之女wow1 小时前
【Hard——Day8】65.有效数字、68.文本左右对齐、76.最小覆盖子串
linux·运维·redis·算法·leetcode
AI大模型学徒2 小时前
NLP基础(八)_马尔可夫模型
算法·机器学习·自然语言处理·nlp·概率论·马尔可夫模型
前端小L2 小时前
图论专题(十八):“逆向”拓扑排序——寻找图中的「最终安全状态」
数据结构·算法·安全·深度优先·图论·宽度优先
前端小L2 小时前
图论专题(十七):从“判定”到“构造”——生成一份完美的「课程表 II」
算法·矩阵·深度优先·图论·宽度优先
qq_433554542 小时前
C++ 稀疏表
开发语言·c++·算法
小白程序员成长日记3 小时前
2025.11.21 力扣每日一题
算法·leetcode·职场和发展
小年糕是糕手4 小时前
【C++】C++入门 -- inline、nullptr
linux·开发语言·jvm·数据结构·c++·算法·排序算法
高洁014 小时前
具身智能-普通LLM智能体与具身智能:从语言理解到自主行动
人工智能·深度学习·算法·aigc·知识图谱