当前位置: 首页 > backend >正文

【优选算法】BFS解决FloodFill算法

在这里插入图片描述

目录

  • FloodFill算法简介
  • 一、[图像渲染](https://leetcode.cn/problems/flood-fill/description/)
  • 二、[岛屿数量](https://leetcode.cn/problems/number-of-islands/description/)
  • 三、[岛屿的最大面积](https://leetcode.cn/problems/max-area-of-island/description/)
  • 四、[被围绕的区域](https://leetcode.cn/problems/surrounded-regions/description/)
  • 结尾

FloodFill算法简介

Flood Fill 算法(漫水填充算法)是一种经典的图像处理技术,用于将连通区域内的所有像素替换为指定颜色。

核心思想

从起始点开始,递归或迭代地将与其连通且颜色相同的所有像素替换为目标颜色,直到所有连通像素被处理完毕。


一、图像渲染

题目描述

在这里插入图片描述

思路讲解
本道题会给我们起始点和目标颜色 ,让我们将二维数组中起始点与起始点连通并且与起始点颜色相同点的值修改为目标颜色 ,这里使用BFS解决,通过队列逐层处理所有与起始点原始颜色相同的连通像素(上下左右四个方向),并将其替换为目标颜色。以下是具体思路:

  1. 本道题需要在原二维数组中进行修改,这里先将 [sr, sc] 位置上的值保存为 oldcolor
  2. 将起始点 [sr, sc] 加入队列,作为 BFS 的起点,并立即将其颜色改为 color
  3. 重复以下步骤,直到队列为空
    • 从队列中取出一个点 [r, c],遍历其四个相邻点 [nr, nc]
    • 对每个相邻点,检查是否在二维数组范围内且颜色为 oldcolor
    • 若符合条件,将其颜色改为 color,并加入队列,继续处理其相邻点
  4. 所有连通区域已处理完毕,返回修改后的二维数组

编写代码

class Solution {// 坐标上下左右需要加的数int dx[4] = {0,0,-1,1};int dy[4] = {1,-1,0,0};
public:vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc , int color) {if (image[sr][sc] == color)return image;int rows = image.size() , cols = image[0].size();queue<pair<int, int>> qu;int oldcolor = image[sr][sc];qu.push({sr, sc});while(!qu.empty()){int qu_x = qu.front().first, qu_y = qu.front().second;image[qu_x][qu_y] = color;qu.pop();for(int i = 0 ; i < 4 ; i++){int x = qu_x + dx[i] , y = qu_y + dy[i] ;if(x >= 0 && x < rows && y >=0 && y < cols && image[x][y] == oldcolor)qu.push({x,y});}}return image;}
};

二、岛屿数量

题目描述
在这里插入图片描述

思路讲解
本道题给我们一个二维数组,想让我们找出岛屿的数量。

遍历二维数组中的每个位置,当遇到未访问的陆地(‘1’)时,通过 BFS 将其连通的所有陆地标记为 “已访问”(避免重复计数),并计数为一个岛屿,以下是具体思路:

  1. 初始化岛屿数量为 0,创建一个与原二维数组同等规模的二维数组,并全部初始化为false,表示该位置没有被访问过
  2. 依次检查网格中的每个位置 [i, j]
  3. 若当前位置为 ‘1’ 并且未被访问过,则岛屿数量加 1,并使用 BFS 处理整个连通岛屿
  4. BFS 标记连通陆地:
    • 将当前陆地 [i, j] 加入队列,并立即标记为 true(表示已访问,避免重复处理)
    • 从队列中取出陆地,遍历其上下左右四个方向的相邻位置
    • 对每个相邻位置,若在网格范围内且为 ‘1’ 并且未被访问过,则标记为 true 并加入队列,继续扩展处理
  5. 遍历完所有位置后,返回岛屿数量

实际上标记岛屿已被访问,可以将 ‘1’ 改为 ‘0’ ,但是我这里为了不修改原数组,就创建一个二维数组,对应原二维数组,标记该位置是否访问过。

编写代码

class Solution {int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};public:int numIslands(vector<vector<char>>& grid) {// 与grid同规模的数组,false代表还没走过,true代表已经走过vector<vector<bool>> vis(grid.size(),vector<bool>(grid[0].size(), false));queue<pair<int, int>> qu;int ans = 0;int rows = grid.size(), cols = grid[0].size();for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (grid[i][j] == '1' && vis[i][j] == false) {ans++;vis[i][j] = true;qu.push({i, j});while (!qu.empty()) {int qu_x = qu.front().first, qu_y = qu.front().second;qu.pop();for (int k = 0; k < 4; k++) {int x = qu_x + dx[k], y = qu_y + dy[k];if(x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == '1' && vis[x][y] == false){vis[x][y] = true;qu.push({x,y});}}}}}}return ans;}
};

三、岛屿的最大面积

题目描述
在这里插入图片描述

思路讲解
本道题给我们一个二维数组,想让我们找出最大岛屿。

遍历二维数组中的每个点,当遇到未访问的陆地(‘1’)时,通过 BFS 将其连通的所有陆地标记为 “已访问”(避免重复计数),并在BFS的过程中记录岛屿的大小,通过对比得到最大岛屿的大小,以下是具体思路:

  1. 初始化最多岛屿大小为 0,创建一个与原二维数组同等规模的二维数组,并全部初始化为false,表示该位置没有被访问过
  2. 依次检查二维数组中的每个点 [i, j]
  3. 若当前点为 ‘1’ 并且未被访问过,则岛屿数量加 1,并使用 BFS 处理整个连通岛屿
  4. BFS 标记连通陆地并记录陆地大小:
    • 初始化当前岛屿大小为0
    • 将当前陆地 [i, j] 加入队列,并立即标记为 true(表示已访问,避免重复处理)
    • 从队列中取出陆地,遍历其上下左右四个方向的相邻点
    • 对每个相邻点,若在二维数组范围内且为 ‘1’ 并且未被访问过,则将改点标记为 true ,加入队列并将当前岛屿大小+1,继续扩展处理
    • 一次BFS完成后,将当前岛屿大小与最大岛屿大小进行对比,获得最新最大岛屿大小
  5. 遍历完所有点后,返回岛屿数量

实际上标记岛屿已被访问,可以将 ‘1’ 改为 ‘0’ ,但是我这里为了不修改原数组,就创建一个二维数组,对应原二维数组,标记该点是否访问过。

编写代码

class Solution {int dx[4] = {0,0,-1,1};int dy[4] = {1,-1,0,0};
public:int maxAreaOfIsland(vector<vector<int>>& grid) {vector<vector<bool>> vis(grid.size(),vector<bool> (grid[0].size(),false));queue<pair<int,int>> qu;int rows = grid.size() , cols = grid[0].size();int ans = 0;for(int i = 0 ; i < rows ; i++){for(int j = 0 ; j < cols ; j++){if(grid[i][j] == 1 && vis[i][j] == false){qu.push({i,j});vis[i][j] = true;int tmp_max = 1;while(!qu.empty()){int qu_x = qu.front().first , qu_y = qu.front().second;qu.pop();for(int k = 0 ; k < 4 ; k++){int x = qu_x + dx[k] , y = qu_y + dy[k];if(x >= 0 && x < rows && y >= 0 && y < cols && grid[x][y] == 1 && vis[x][y] == false){vis[x][y] = true;qu.push({x,y});tmp_max++;}}}if(tmp_max > ans)ans = tmp_max;}}}return ans;}
};

四、被围绕的区域

题目描述
在这里插入图片描述

思路讲解
本道题给我们一个二维数组,想让我们将被 ‘X’ 包围的 'O’区域中的 ‘O’ 全部替换为 ‘X’,但是想直接找到被 ‘X’ 包围的 ‘O’ 并替换为 'X’需要两个步骤,首先是通过一次BFS判断该区域是否被包围,再通过一次BFS将被 ‘X’ 包围的 ‘O’ 替换为 ‘X’。

正向麻烦的话,就可以反向思考。先找出所有不被围绕的 ‘O’(即位于二维数组边缘或与边缘 ‘O’ 相连的 ‘O’),并将这些 ‘O’ 替换处 ‘O’ 和 ‘X’ 以外的字符;然后将剩余的 ‘O’(被围绕的区域)替换为 ‘X’。以下是具体思路:

  1. 遍历二维数组中边缘四条边中的每个位置 [i, j]
  2. 若当前位置为 ‘O’ ,将 ‘O’ 替换为 ‘H’,并使用 BFS 处理整个连通区域
  3. BFS 处理连通区域:
    • 将当前位置 [i, j] 加入队列
    • 从队列中取出位置,遍历其上下左右四个方向的相邻位置
    • 对每个相邻w位置,若在二维数组范围内且为 ‘O’ ,将 ‘O’ 替换为 ‘H’,继续扩展处理
  4. 将二维数组中所有的 ‘O’ 替换 ‘X’
  5. 将二维数组中所有的 ‘H’ 替换 ‘O’
  6. 处理完毕后,返回二维数组

编写代码

class Solution {int dx[4] = {0, 0, -1, 1};int dy[4] = {1, -1, 0, 0};int rows, cols;public:void bfs(vector<vector<char>>& board, vector<vector<bool>>& vis, int row , int col) {queue<pair<int, int>> qu;qu.push({row, col});board[row][col] = 'H';while (!qu.empty()) {int qu_x = qu.front().first, qu_y = qu.front().second;qu.pop();for (int k = 0; k < 4; k++) {int x = qu_x + dx[k], y = qu_y + dy[k];if (x >= 0 && x < rows && y >= 0 && y < cols &&board[x][y] == 'O' && vis[x][y] == false) {board[x][y] = 'H';qu.push({x, y});}}}}void solve(vector<vector<char>>& board) {rows = board.size(), cols = board[0].size();vector<vector<bool>> vis(rows, vector<bool>(cols, false));for (int i = 0; i < cols; i++) {if (board[0][i] == 'O' && vis[0][i] == false) {bfs(board, vis, 0 , i);}if (board[rows - 1][i] == 'O' && vis[rows - 1][i] == false) {bfs(board, vis, rows - 1, i);}}for (int i = 0; i < rows; i++) {if (board[i][0] == 'O' && vis[i][0] == false) {bfs(board, vis, i, 0);}if (board[i][cols - 1] == 'O' && vis[i][cols - 1] == false) {bfs(board, vis, i, cols - 1);}}for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (board[i][j] == 'O')board[i][j] = 'X';else if (board[i][j] == 'H')board[i][j] = 'O';}}}
};

结尾

如果有什么建议和疑问,或是有什么错误,大家可以在评论区中提出。
希望大家以后也能和我一起进步!!🌹🌹
如果这篇文章对你有用的话,希望大家给一个三连支持一下!!🌹🌹

在这里插入图片描述

http://www.xdnf.cn/news/16398.html

相关文章:

  • 零基础学习性能测试第五章:JVM性能分析与调优-GC垃圾分代回收机制与优化
  • 死锁出现的原因
  • 《计算机组成原理与汇编语言程序设计》实验报告四 Debug及指令测试
  • #影·数学计划# N1 一元一次方程讲解 未完待续
  • 基于STM32的智能康养木屋监测系统
  • vector使用和模拟
  • 在本地环境中运行 ‘dom-distiller‘ GitHub 库的完整指南
  • openshift AI 2.22安装的需求
  • 人工智能与城市:城市生活的集成智能
  • 基于 LSTM 与 SVM 融合的时间序列预测模型:理论框架与协同机制—实践算法(1)
  • Wireshark TS | 发送数据超出接收窗口
  • Frontiers in Psychology投稿LaTeX(三)
  • 元宇宙中的“虫洞“:技术实现、应用场景与未来挑战
  • J3160迷你小主机 性能测试 对比i3-4170 以及服务器
  • Python Pandas.qcut函数解析与实战教程
  • RS485转profinet网关如何让JRT激光测距传感器开启自动模式连续测量模式
  • 数据结构基础内容(第九篇:最短路径)
  • DP之背包基础
  • AutoLabelImg:高效的数据自动化标注工具和下载
  • Gradio.NET 中文快速入门与用法说明
  • 2025年7月25日-7月26日 · AI 今日头条
  • 在Luckfox Lyra(Zero W)上将TF卡格式化为ext4文件系统
  • 《 集成异步任务与定时调度:线程池与任务中心设计》
  • AI与区块链Web3技术融合:重塑数字经济的未来格局
  • 2025年项目数据看板工具选型指南,精选12款
  • SQL中的group by和having区别详解
  • 【C语言网络编程】HTTP 客户端请求(基于 Socket 的完整实现)
  • 神经网络知识讨论
  • 网易大模型算法岗面经80道
  • 【学习笔记】MimicGen: 基于人类演示的可扩展机器人学习数据生成系统