BFS解决FloodFill问题(Leetcode,733.图像渲染,200.岛屿数量,130.被围绕的区域)

 利用宽度优先搜索的方法结合列表解决数组中的相同元素区域性问题, 找到满足条件的位置后开始BFS若周围有满足条件的点,继续BFS直到周围没有满足条件的点。下面三道题分别是修改区域元素内容,寻找有多少个满足条件的区域和修改特定位置的区域元素内容。思路上是相同的,只有细微的差别。

733.图像渲染 

LeetCode,733.图像渲染

class Solution {
public:
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color) {
   
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    int m = image.size(),n=image[0].size();
    
    int pre=image[sr][sc];//记录选定位置颜色
    if(pre==color) return image;
    //如果选定位置颜色为目标颜色,则直接返回
   
    queue<pair<int,int>> q;
    q.push({sr,sc});
     //建立一个列表并将初始位置坐标加入列表
    while(q.size())//开始宽度优先搜索
    {
        
        auto[a,b]=q.front();
        q.pop();
        //获取最前方坐标,并将此位置移除出列表
        
        image[a][b]=color;//修改为目标颜色

        for(int i = 0;i<4;i++)
        {
            int x = a+dx[i],y = b+dy[i];
            //对上下左右四个方向进行遍历
            if(y<n&&x<m&&y>=0&&x>=0&&image[x][y]==pre)
            {
                q.push({x,y});
                //若满足条件则将该坐标加入队列中以便继续搜索
            }
        }
    }
    return image;
    }
};

200.岛屿数量



LeetCode,200.岛屿数量

class Solution {
public:
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    bool vim[301][301]={false};
    //用于判定该位置是否搜索过,false为没有,true为搜索过
   
    int numIslands(vector<vector<char>>& grid) {
        int 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'&&vim[i][j] ==false)
                {
                    ret++;
                    floodFill(grid,i,j);
                    //在遍历过程中找到岛屿之后开始BFS
                    //floodFill能将邻接的位置全部标记为已经搜索过
                }
            }
        }

        return ret;
    }
   
    void floodFill(vector<vector<char>>& image, int sr, int sc) {
    int m = image.size(),n=image[0].size();
    if(image[sr][sc]=='0') return ;
    queue<pair<int,int>> q;
    q.push({sr,sc});
    //先将当前位置加入队列
    while(q.size())
    {
        
        auto[a,b]=q.front();
        q.pop();
        //获取开头位置然后将该位置删除
        
        vim[a][b]=true;
        //表示已经搜索过
        
        for(int i = 0;i<4;i++)
        {
            int x = a+dx[i],y = b+dy[i];//获取四周位置坐标
            if(y<n&&x<m&&y>=0&&x>=0&&image[x][y]=='1'&&vim[x][y]!=true)
            {
                q.push({x,y});
                vim[x][y]=true;
                //标记位置
            }
        }
    }
    return ;
    }

};

130.被围绕的区域 

LeetCode,130.被围绕的区域

class Solution {
public:
    int dx[4]={0,0,1,-1};
    int dy[4]={1,-1,0,0};
    void solve(vector<vector<char>>& board) {
        int m = board.size(),n = board[0].size();
        
        接下来两个for循环的目的是将与边缘位置相连的O全部处理为另一个字符
        for(int i = 0;i<n;i++)
        {
            if(board[0][i]=='O')bfs(board,0,i,'*');
            if(board[m-1][i]=='O') bfs(board,m-1,i,'*');
        }
        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,'*');
        } 

    //遍历处理后的数组,若为O则为被X包围的,变为X,若为*则为原先与边缘相连的O,再将其还原为O   
    for(int i = 0;i<m;i++)
    {
        for(int j = 0;j<n;j++)
        {
            if(board[i][j]=='*') board[i][j]='O';
            else if(board[i][j]=='O') board[i][j]='X';
        }        
    }
    return ;
    }
    
    //从i,j位置开始,将与i,j相同且相连的一片区域内的元素变为符号 s
    void bfs(vector<vector<char>>& board,int i ,int j ,char s)
    {
        int m = board.size(),n = board[0].size();
        queue<pair<int,int>>q;
        q.push({i,j});
        board[i][j]=s;
        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')
                {
                    q.push({x,y});
                    board[x][y]=s;
                }
            }
        }
        return ;
    }

};

以上就是三道题的代码,笔者认为注释已经很清楚了,尤其是第一道的代码注释,建议这三道题一块去做,更容易理解BFS去解决这类型的问题。

欢迎大家在评论区交流讨论,批评指正。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
你好!对于LeetCode上的问题994.腐烂的橘子,你可以使用Python来解决。下面是一个示例代码: ```python from collections import deque def orangesRotting(grid): # 记录网格的行数和列数 row, col = len(grid), len(grid[0]) # 定义四个方向:上、下、左、右 directions = [(-1, 0), (1, 0), (0, -1), (0, 1)] # 使用队列来保存腐烂的橘子的位置 queue = deque() # 记录新鲜橘子的数量 fresh_count = 0 # 遍历整个网格,初始化队列和新鲜橘子的数量 for i in range(row): for j in range(col): if grid[i][j] == 2: # 腐烂的橘子 queue.append((i, j)) elif grid[i][j] == 1: # 新鲜橘子 fresh_count += 1 # 如果新鲜橘子的数量为0,直接返回0 if fresh_count == 0: return 0 # 初始化分钟数 minutes = 0 # 开始进行BFS,直到队列为空 while queue: # 记录当前分钟数下,队列中的元素数量 size = len(queue) # 遍历当前分钟数下的所有腐烂的橘子 for _ in range(size): x, y = queue.popleft() # 遍历四个方向 for dx, dy in directions: nx, ny = x + dx, y + dy # 判断新位置是否在网格内,并且是新鲜橘子 if 0 <= nx < row and 0 <= ny < col and grid[nx][ny] == 1: # 将新鲜橘子变为腐烂状态 grid[nx][ny] = 2 # 将新鲜橘子的位置加入队列 queue.append((nx, ny)) # 新鲜橘子的数量减1 fresh_count -= 1 # 如果当前分钟数下,没有新鲜橘子了,结束循环 if fresh_count == 0: break # 每遍历完一层,分钟数加1 minutes += 1 # 如果最后还有新鲜橘子,返回-1,否则返回分钟数 return -1 if fresh_count > 0 else minutes ``` 你可以将给定的网格作为参数传递给`orangesRotting`函数来测试它。请注意,该代码使用了BFS算法来遍历橘子,并计算腐烂的分钟数。希望能对你有所帮助!如果有任何疑问,请随时问我。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值