C++算法:BFS解决FloodFill算法

BFS解决FloodFill算法

1.图像渲染

FloodFill用BFS解决,从某个元素开始,入队列;执行一系列操作;再准备两个数组dx,dy,辅助遍历上下左右相邻元素。

有时也需要同样规模的标记数组visited,例如imagex y已被遍历,则对应visitedx y记为1,避免重复遍历陷入死循环。本题可以不使用标记数组,如果初始坐标的原始颜色与color相同时,直接结束返回image即可。

cpp 复制代码
class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)
    {
        int start = image[sr][sc];
        if (start == color)
            return image;
        int m = image.size(), n = image[0].size();
        int dx[] = { -1,1,0,0 };
        int dy[] = { 0,0,-1,1 };
        queue<pair<int, int>> q;

        q.push({ sr,sc });
        while (!q.empty())
        {
            auto [a, b] = q.front();//C++17
            q.pop();

            image[a][b] = color;

            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) && image[x][y] == start)
                    q.push({ x,y });
            }
        }
        return image;
    }
};

2.岛屿数量

与上一题类似,此题要用到visited数组。在用dx,dy辅助遍历数组时,新坐标入队列后应该立刻在visited数组中记为1,否则会超时。

cpp 复制代码
class Solution
{
    int dx[4] = { 1,-1,0,0 };
    int dy[4] = { 0,0,1,-1 };
    int visited[300][300] = { 0 };
public:
    int numIslands(vector<vector<char>>& grid)
    {
        int m = grid.size(), n = grid[0].size();

        int ret = 0;
        queue<pair<int, int>> q;
        for (int i = 0;i < m;i++)
        {
            for (int j = 0;j < n;j++)
            {
                if (grid[i][j] == '0' || visited[i][j] == 1)
                    continue;
                q.push({ i,j });
                visited[i][j] = 1;
                while (!q.empty())
                {
                    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' && visited[x][y] == 0)
                        {
                            q.push({ x,y });
                            visited[x][y] = 1;
                        }
                    }
                }
                ret++;
            }
        }
        return ret;
    }
};

3.岛屿的最大面积

只需要在BFS过程中记录面积即可。

cpp 复制代码
class Solution
{
    int dx[4] = { 0,0,1,-1 };
    int dy[4] = { 1,-1,0,0 };
    int visited[50][50] = { 0 };
public:
    int maxAreaOfIsland(vector<vector<int>>& grid)
    {
        int m = grid.size(), n = grid[0].size();
        int ret = 0;
        queue<pair<int, int>> q;
        for (int i = 0;i < m;i++)
        {
            for (int j = 0;j < n;j++)
            {
                if (grid[i][j] == 0 || visited[i][j] == 1)
                    continue;
                int s = 0;  //面积
                q.push({ i,j });
                visited[i][j] = 1;
                while (!q.empty())
                {
                    auto [a, b] = q.front();
                    q.pop();
                    s++;
                    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 && visited[x][y] == 0)
                        {
                            q.push({ x,y });
                            visited[x][y] = 1;
                        }
                    }
                }
                ret = max(ret, s);
            }
        }
        return ret;
    }
};

4.被围绕的区域

理解题意,上下左右相邻且元素都为字符O视作一个连通块,如果这个连通块被字符X包围,则把这个连通块的所有元素改为字符X;如果连通块中存在元素位于矩阵的四个边缘,则该连通块不被字符X包围。

遍历矩阵,对每个连通块BFS,如果被字符X完全包围,则进行处理,否则不处理。显然这个方法是比较麻烦的,我们可以采用正难则反的思想,先遍历矩阵的四个边缘,把字符O的连通块全部改为字符 ! ,再遍历矩阵,此时矩阵内的字符O连通块都必定是被字符X包围的,直接把字符O改为字符X,同时把字符 ! 恢复为字符O。

cpp 复制代码
class Solution
{
    int dx[4] = { 0,0,-1,1 };
    int dy[4] = { 1,-1,0,0 };
    int m = 0, n = 0;
public:
    void solve(vector<vector<char>>& board)
    {
        m = board.size(), n = board[0].size();

        //遍历0行、m-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);
        }

        //遍历0列、n-1列
        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 i = 0;i < m;i++)
        {
            for (int j = 0;j < n;j++)
            {
                if (board[i][j] == 'O')
                    board[i][j] = 'X';
                if (board[i][j] == '!')
                    board[i][j] = 'O';
            }
        }
    }
    void BFS(vector<vector<char>>& board, int i, int j)
    {
        queue<pair<int, int>> q;
        q.push({ i,j });
        board[i][j] = '!';
        while (!q.empty())
        {
            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')
                {
                    q.push({ x,y });
                    board[x][y] = '!';
                }
            }
        }
    }
};
相关推荐
find1star6 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing7 小时前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB21127 小时前
力扣160 21 86
算法·leetcode·职场和发展
Tairitsu_H7 小时前
[C++] 深入理解红黑树:封装set与map
开发语言·c++·set·map·红黑树·模拟实现
小智老师PMP8 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN8 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
a187927218318 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解
江畔柳前堤9 小时前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native
文心快码BaiduComate9 小时前
2026 OPC x AI Coding 趋势案例交流会圆满落幕:一个人就一支研发团队
算法
ACM-moran10 小时前
条件显化(二分单峰函数+构造数列)
算法·推公式·整数三分