BFS 解决 FloodFill 算法(典型算法思想)—— OJ例题算法解析思路
目录
一、733. 图像渲染 - 力扣(LeetCode)
算法代码:
算法思路
基础参数
函数入口
检查条件
初始化 BFS
BFS 填充过程
返回结果
复杂度分析
总结
二、200. 岛屿数量 - 力扣(LeetCode)
算法代码:
算法思路
基础参数
函数入口
遍历网格
BFS 遍历
返回结果
复杂度分析
总结
三、695. 岛屿的最大面积 - 力扣(LeetCode)
算法代码:
算法思路
基础参数
函数入口
遍历网格
BFS 遍历
返回结果
复杂度分析
总结
四、130. 被围绕的区域 - 力扣(LeetCode)
算法代码:
算法思路
基础参数
函数入口
处理边界上的 'O' 区域
还原棋盘
BFS 遍历
复杂度分析
总结
一、733. 图像渲染 - 力扣(LeetCode)


算法代码:
class Solution {typedef pair<int, int> PII; // 定义坐标对int dx[4] = {0, 0, 1, -1}; // 四个方向的x偏移量int dy[4] = {1, -1, 0, 0}; // 四个方向的y偏移量public: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 m = image.size(), n = image[0].size(); // 获取图像的尺寸queue<PII> q; // 初始化队列q.push({sr, sc}); // 将起始坐标入队while (!q.empty()) { // BFS循环auto [a, b] = q.front(); // 获取队首元素image[a][b] = color; // 将当前点的颜色设为目标颜色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 && image[x][y] == prev) {q.push({x, y}); // 将符合条件的坐标入队}}}return image; // 返回填充后的图像}
};
算法思路

-
基础参数
-
使用
typedef pair<int, int> PII定义一个坐标对,方便存储和操作点的坐标。 -
dx和dy数组用于表示四个方向的移动(右、左、下、上)。
-
-
函数入口
-
floodFill函数接收一个图像image(二维数组),起始坐标sr和sc,以及要填充的颜色color。
-
-
检查条件
-
首先获取起始点的原始颜色
prev,如果该颜色已经是目标颜色color,则直接返回原图像,避免不必要的操作。
-
-
初始化 BFS
-
获取图像的尺寸
m和n。 -
使用一个队列
q来管理待处理的坐标。 -
将起始坐标
(sr, sc)入队。
-
-
BFS 填充过程
-
进入循环,直到队列为空:
-
从队列中取出当前坐标
(a, b)。 -
将该坐标的颜色设置为
color。 -
遍历四个方向,计算相邻坐标
(x, y)。 -
检查新坐标是否在图像范围内,以及该坐标的颜色是否与
prev相同。如果满足条件,则将新坐标入队。
-
-
-
返回结果
-
循环结束后,返回填充后的图像。
-
复杂度分析
-
时间复杂度:O(N),N 为图像中像素的总数。在最坏情况下,所有像素都可能被访问。
-
空间复杂度:O(N),队列在最坏情况下可能需要存储所有的像素。
总结
这个实现有效地解决了洪水填充问题,通过广度优先搜索遍历所有与起始点相连的相同颜色区域并将其填充为目标颜色。可以根据需要调整该实现以适应更复杂的场景或者使用 DFS(深度优先搜索)来实现同样的功能。
二、200. 岛屿数量 - 力扣(LeetCode)

算法代码:
class Solution {int dx[4] = {1, -1, 0, 0}; // 表示上下左右的x偏移int dy[4] = {0, 0, 1, -1}; // 表示上下左右的y偏移bool vis[301][301]; // 记录访问状态int m, n; // 网格的行数和列数public: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); // 用BFS标记这个岛屿}}}return ret; // 返回岛屿总数}void bfs(vector<vector<char>>& grid, int i, int j) {queue<pair<int, int>> q; // 初始化队列q.push({i, j}); // 入队当前坐标vis[i][j] = true; // 标记为已访问while (q.size()) { // BFS循环auto [a, b] = q.front(); // 获取队首元素q.pop(); // 移除队首元素for (int k = 0; k < 4; k++) { // 遍历四个方向int x = a + dx[k], y = b + dy[k]; // 计算相邻坐标// 检查是否在边界内,并且为 '1' 且未访问if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == '1' && !vis[x][y]) {q.push({x, y}); // 入队vis[x][y] = true; // 标记为已访问}}}}
};
算法思路

-
基础参数
-
使用
dx和dy数组来表示四个方向的移动(上下左右)。 -
vis数组用于标记已经访问过的网格,避免重复计算。
-
-
函数入口
-
numIslands函数接收一个二维网格grid作为输入,返回岛屿的数量。
-
-
遍历网格
-
计算网格的行数
m和列数n。 -
使用双重循环遍历每个格子:
-
当遇到
'1'且未被访问过时,说明找到了一个新的岛屿,计数器ret加一,并调用bfs函数来遍历和标记这个岛屿的所有部分。
-
-
-
BFS 遍历
-
在
bfs函数中:-
初始化一个队列,将当前陆地坐标入队,并将其标记为已访问。
-
进入循环,直到队列为空:
-
从队列中取出当前坐标
(a, b)。 -
遍历四个方向,计算相邻坐标
(x, y)。 -
检查新坐标是否在网格范围内,且该坐标为
'1'且未被访问过。如果满足条件,则将新坐标入队并标记为已访问。
-
-
-
-
返回结果
-
循环完成后,返回计数器
ret的值,表示岛屿的总数量。
-
复杂度分析
-
时间复杂度:O(M * N),其中 M 是行数,N 是列数。在最坏情况下,所有格子都可能被访问一次。
-
空间复杂度:O(M * N),用于存储访问状态
vis,在最坏情况下,可能需要存储整个网格的状态。
总结
这个实现有效地解决了“岛屿数量”问题,通过广度优先搜索(BFS)遍历所有相连的陆地('1'),并将其标记为已访问,以避免重复计数。可以根据需要将 BFS 替换为深度优先搜索(DFS)以实现相同的功能。总之,该算法能够高效地计算出网格中的岛屿数量,尤其适用于处理大型的二维网格问题。
三、695. 岛屿的最大面积 - 力扣(LeetCode)


算法代码:
class Solution {int dx[4] = {0, 0, 1, -1}; // 表示上下左右的x偏移int dy[4] = {1, -1, 0, 0}; // 表示上下左右的y偏移bool vis[51][51]; // 记录访问状态(假设最大网格为51x51)int m, n; // 网格的行数和列数public:int maxAreaOfIsland(vector<vector<int>>& 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 = max(ret, bfs(grid, i, j)); // 计算岛屿面积并更新最大面积}}}return ret; // 返回最大岛屿面积}int bfs(vector<vector<int>>& grid, int i, int j) {int count = 0; // 初始化当前岛屿面积计数queue<pair<int, int>> q; // 初始化队列q.push({i, j}); // 入队当前坐标vis[i][j] = true; // 标记为已访问count++; // 当前岛屿面积增加while (q.size()) { // BFS循环auto [a, b] = q.front(); // 获取队首元素q.pop(); // 移除队首元素for (int k = 0; k < 4; k++) { // 遍历四个方向int x = a + dx[k], y = b + dy[k]; // 计算相邻坐标// 检查是否在边界内,并且为 '1' 且未访问if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] == 1 && !vis[x][y]) {q.push({x, y}); // 入队vis[x][y] = true; // 标记为已访问count++; // 增加岛屿面积}}}return count; // 返回当前岛屿的面积}
};
算法思路
-
基础参数
-
dx和dy数组用来表示四个方向的移动(右、左、下、上)。 -
vis数组用于标记已经访问过的格子,以避免重复计算。
-
-
函数入口
-
maxAreaOfIsland函数接收一个二维网格grid作为输入,返回最大的岛屿面积。
-
-
遍历网格
-
计算网格的行数
m和列数n。 -
使用双重循环遍历每个格子:
-
当遇到
1(陆地)且未被访问过时,调用bfs函数来计算这个岛屿的面积,并更新最大面积ret。
-
-
-
BFS 遍历
-
在
bfs函数中:-
初始化一个计数器
count用于记录岛屿的面积。 -
将当前陆地坐标入队,并标记为已访问,同时将
count增加。 -
进入循环,直到队列为空:
-
从队列中取出当前坐标
(a, b)。 -
遍历四个方向,计算相邻坐标
(x, y)。 -
检查新坐标是否在网格范围内,且该坐标为
1且未被访问过。如果满足条件,则将新坐标入队并标记为已访问,同时增加count。
-
-
-
-
返回结果
-
循环完成后,返回最大的岛屿面积
ret。
-
复杂度分析
-
时间复杂度:O(M * N),其中 M 是行数,N 是列数。在最坏情况下,所有格子都可能被访问一次。
-
空间复杂度:O(M * N),用于存储访问状态
vis,在最坏情况下,可能需要存储整个网格的状态。
总结
这个实现有效地解决了“最大岛屿面积”问题,通过广度优先搜索(BFS)遍历所有相连的陆地(1),并计算其面积。该算法能够高效地找到最大的岛屿面积,尤其适用于处理大型的二维网格问题。如果需要,也可以将 BFS 替换为深度优先搜索(DFS)以实现相同的功能。总之,该算法能够在给定的网格中快速找到并计算最大岛屿的面积。
四、130. 被围绕的区域 - 力扣(LeetCode)

算法代码:
class Solution {int dx[4] = {0, 0, 1, -1}; // 表示上下左右的x偏移int dy[4] = {1, -1, 0, 0}; // 表示上下左右的y偏移int m, n; // 棋盘的行数和列数public:void solve(vector<vector<char>>& board) {m = board.size(); // 获取行数n = board[0].size(); // 获取列数// 1. 处理边界上的 'O' 联通块,全部修改成 '.'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++) {if (board[i][0] == 'O') // 第一列bfs(board, i, 0);if (board[i][n - 1] == 'O') // 最后一列bfs(board, i, n - 1);}// 2. 还原剩余的区域for (int i = 0; i < m; i++) {for (int j = 0; j < n; j++) {if (board[i][j] == 'O') // 被围住的区域变为 'X'board[i][j] = 'X';else if (board[i][j] == '.') // 安全的区域还原为 'O'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.size()) { // BFS循环auto [a, b] = q.front(); // 获取队首元素q.pop(); // 移除队首元素for (int k = 0; k < 4; k++) { // 遍历四个方向int x = a + dx[k], y = b + dy[k]; // 计算相邻坐标// 检查是否在边界内,并且为 'O'if (x >= 0 && x < m && y >= 0 && y < n && board[x][y] == 'O') {q.push({x, y}); // 入队board[x][y] = '.'; // 标记为已访问(安全)}}}}
};
算法思路

-
基础参数
-
dx和dy数组用来表示四个方向的移动(上下左右)。 -
m和n分别表示棋盘的行数和列数。
-
-
函数入口
-
solve函数接收一个二维棋盘board,用于处理其中的'O'区域。
-
-
处理边界上的
'O'区域-
通过双重循环遍历棋盘的边界(第一行、最后一行、第一列、最后一列):
-
当遇到
'O'时,调用bfs函数,将其和与之相连的所有'O'修改为'.',表示这些'O'是安全的,不会被围住。
-
-
-
还原棋盘
-
遍历整个棋盘,将剩余的
'O'(被围住的)改为'X',将'.'还原为'O'。
-
-
BFS 遍历
-
在
bfs函数中:-
初始化一个队列,将当前坐标入队,并将其改为
'.'。 -
进入循环,直到队列为空:
-
从队列中取出当前坐标
(a, b)。 -
遍历四个方向,计算相邻坐标
(x, y)。 -
检查新坐标是否在棋盘范围内,且该坐标为
'O',如果满足条件,则将新坐标入队并改为'.'。
-
-
-
复杂度分析
-
时间复杂度:O(M * N),其中 M 是行数,N 是列数。在最坏情况下,所有格子都可能被访问一次。
-
空间复杂度:O(M * N),用于存储队列和处理访问状态,尤其当整个棋盘都是
'O'时,队列可能存储整个棋盘。
总结
这个实现有效地解决了“被围绕的区域”问题,通过广度优先搜索(BFS)遍历所有与边界相连的 'O',并将其标记为安全区域。最终,该算法能够高效地将被围住的区域转变为 'X',而保证与边界相连的 'O' 区域保持不变。该算法非常适合处理类似的二维网格问题,通过 BFS 的方式可以灵活地处理不同的边界条件和连通性问题。
相关文章:
BFS 解决 FloodFill 算法(典型算法思想)—— OJ例题算法解析思路
目录 一、733. 图像渲染 - 力扣(LeetCode) 算法代码: 算法思路 基础参数 函数入口 检查条件 初始化 BFS BFS 填充过程 返回结果 复杂度分析 总结 二、200. 岛屿数量 - 力扣(LeetCode) 算法代码:…...
纷析云开源版- Vue2-增加字典存储到localStorage
main.js //保存字典数据到LocalStorage Vue.prototype.$api.setting.SystemDictType.all().then(({data}) > {loadDictsToLocalStorage(data) })新增 dictionary.js 放在 Utils文件夹里面 // 获取字典数据 export function getDictByType(dictType) {const dicts JSON.par…...
Python 爬虫selenium
1.selenium自动化 selenium可以操作浏览器,在浏览器页面上实现:点击、输入、滑动 等操作。 不同于selenium自动化,逆向本质是: 分析请求,例如:请求方法、请求参数、加密方式等。用代码模拟请求去实现同等…...
前端导出word文件,并包含导出Echarts图表等
基础导出模板 const html <html><head><style>body {font-family: Times New Roman;}h1 {text-align: center;}table {border-collapse: collapse;width: 100%;color: #1118FF;font-weight: 600;}th,td {border: 1px solid black;padding: 8px;text-align: …...
【复现DeepSeek-R1之Open R1实战】系列8:混合精度训练、DeepSpeed、vLLM和LightEval介绍
这里写目录标题 1 混合精度训练1.1 FP16和FP321.2 优点1.3 存在的问题1.4 解决办法 2 DeepSpeed3 vLLM3.1 存在的问题3.2 解决方法3.2.1 PagedAttention3.2.2 KV Cache Manager3.2.3 其他解码场景 3.3 结论 4 LightEval4.1 主要功能4.2 使用方法4.3 应用场景 本文继续深入了解O…...
从面试中的“漏掉步骤”谈自我表达与思维方式的转变
在今天的面试中,我遇到了一个让我深刻反思自己思维方式的问题。当面试官问到如何应对用户量和请求量逐渐增加时,我的回答遗漏了一些基础步骤,导致我给出了“我暂时想不出更好的反思”的回答。这一经历让我意识到,在面对问题时&…...
大模型面经:SFT和RL如何影响模型的泛化或记忆能力?
监督微调 (SFT) 和强化学习 (RL)都是目前大模型的基础模型后训练技术,像DeepSeek-R1、kimi等的训练方法都将两种技术应用到了极致。 如何去设计训练步骤(先SFT再RL,还是直接RL)都需要对SFT和RL的能力有较深刻的了解。 本篇就以面…...
力扣-回溯-17 电话号码的字母组合
思路 和之前的回溯不同的是,要遍历完所有的数字,并且在单层递归逻辑里需要遍历一整个字符串 代码 class Solution { public:vector<string> letters {"", "", "abc", "def", "ghi", "…...
大模型幻觉
1.什么是大模型幻觉? 在语言模型的背景下,幻觉指的是一本正经的胡说八道:看似流畅自然的表述,实则不符合事实或者是错误的。 幻觉现象的存在严重影响LLM应用的可靠性,本文将探讨大型语言模型(LLMs)的幻觉问题,以及解决幻觉现象的一些常见方法。 2.为什么需要解决LLM的…...
2025-02-20 学习记录--C/C++-PTA 7-27 冒泡法排序
一、题目描述 ⭐️ 二、代码(C语言)⭐️ /** * 冒泡法实现升序 */#include <stdio.h>int main() {int N, // 整数个数 6K, // 扫描遍数 2num, // 待排序的整数 2 3 5 1 6 4numArr[100], // 待排序的整数合集 2 3 5 1…...
RK3588配置成为路由器
文章目录 前言一、配置netplan二、安装hostapd1.创建hostapd.conf文件2.安装软件3.修改启动文件4.修改/etc/default/hostapd 文件 三、安装dnsmasq服务四、配置NET及重启验证五、常见问题总结 前言 RK3588开发板有两个网口,一个无线网卡。我需要配置为家用路由器模…...
【数据挖掘】--算法
【数据挖掘】--算法 目录:1. 缺失值和数值属性处理1缺失值处理: 2. 用于文档分类的朴素贝叶斯3. 分治法:建立决策树4. 覆盖算法建立规则5. 挖掘关联规则6. 线性模型有效寻找最近邻暴力搜索(Brute-Force Search)kd树&am…...
Huatuo热更新--如何使用
在安装完huatuo热更新插件后就要开始学习如何使用了。 1.创建主框渐Main 新建文件夹Main(可自定义),然后按下图创建文件,注意名称与文件夹名称保持一致 然后新建场景(Init场景),添加3个空物体…...
基于Django快递物流管理可视化分析系统(完整系统源码+数据库+详细开发文档+万字详细论文+答辩PPT+详细部署教程等资料)
文章目录 基于Django快递物流管理可视化分析系统(完整系统源码数据库详细开发文档万字详细论文答辩PPT详细部署教程等资料)一、项目概述二、项目说明三、研究意义四、系统设计技术架构 五、功能实现六、完整系统源码数据库详细开发文档万字详细论文答辩P…...
基于射频开关选择的VNA校准设计
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
解决本地模拟IP的DHCP冲突问题
解决 DHCP 冲突导致的多 IP 绑定失效问题 前言 续接上一篇在本机上模拟IP地址。 在实际操作中,如果本机原有 IP(如 192.168.2.7)是通过 DHCP 自动获取的,直接添加新 IP(如 10.0.11.11)可能会导致 DHCP 服…...
ChromeDriver下载
平时为了下个驱动,到处找挺麻烦,收集了很多无偿分享给需要的人,仅供学习和交流。 ChromeDriver 102.0.5005.61 ChromeDriver 105.0.5195.102 ChromeDriver 108.0.5359.71 ChromeDriver 111.0.5563.64 ChromeDriver 116.0.5845.97 Chrom…...
springboot pagehelper分页插件封装
封装插件: 可自定义返回的Pages实体类参数 package com.wm.common;import com.github.pagehelper.ISelect; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import lombok.Data; import java.util.List;/*** 分页封装* param <…...
Elasticsearch7.1.1 配置密码和SSL证书
生成SSL证书 ./elasticsearch-certutil ca -out config/certs/elastic-certificates.p12 -pass 我这里没有设置ssl证书密码,如果需要设置密码,需要再配置给elasticsearch 在之前的步骤中,如果我们对elastic-certificates.p12 文件配置了密码…...
让win11右键默认显示更多选项
cmd / powershell 右键默认显示更多选项 reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve 刷新,使配置生效(该命令需要cmd执行,powershell不行) …...
毕业项目推荐:基于yolov8/yolo11的100种中药材检测识别系统(python+卷积神经网络)
文章目录 概要一、整体资源介绍技术要点功能展示:功能1 支持单张图片识别功能2 支持遍历文件夹识别功能3 支持识别视频文件功能4 支持摄像头识别功能5 支持结果文件导出(xls格式)功能6 支持切换检测到的目标查看 二、数据集三、算法介绍1. YO…...
kill -9 结束某个用户所有进程的方式-linux019
1. 使用 pkill 命令 pkill 命令可以通过用户名直接终止该用户的所有进程。加上 -9 参数,表示强制结束进程。 pkill -9 -u XXXX 说明:这个命令会使用 SIGKILL 信号(即 kill -9)强制终止 ttlsa 用户的所有进程。 2. 使用 killal…...
自用题库---面试使用
1、css中如何实现水平垂直居中 方法一:flex: display: flex; justify-content: center; align-item: center;方法二:绝对定位margin:auto: position: absolute; left: 0; right: 0; top: 0; bottom: 0; margin:auto;方法三:已…...
蓝桥杯好数
样例输入: 24 输出:7 输入:2024 输出: 150 思路:本题朴素方法的时间复杂度是O(n * log10(n)) ,不超时。主要考察能否逐位取数,注意细节pi,这样不会改变i,否则会导致循环错误。 #in…...
Jenkins 配置 Credentials 凭证
Jenkins 配置 Credentials 凭证 一、创建凭证 Dashboard -> Manage Jenkins -> Manage Credentials 在 Domain 列随便点击一个 (global) 二、添加 凭证 点击左侧 Add Credentials 四、填写凭证 Kind:凭证类型 Username with password: 配置 用…...
用openresty和lua实现壁纸投票功能
背景 之前做了一个随机壁纸接口,但是不知道大家喜欢对壁纸的喜好,所以干脆在实现一个投票功能,让用户给自己喜欢的壁纸进行投票。 原理说明 1.当访问http://demo.com/vote/时,会从/home/jobs/webs/imgs及子目录下获取图片列表&…...
Vue 监听属性(watch)
Vue 渐进式JavaScript 框架 基于Vue2的学习笔记 - Vue 监听属性(watch) 目录 监听属性 监听值改变 使用watch实现 区别 总结 监听属性 通过watch来响应数据的变化。 虽然大多数情况计算属性都可以满足需要,但有时还是需要使用侦听器。…...
mysql查看binlog日志
mysql 配置、查看binlog日志: 示例为MySQL8.0 1、 检查binlog开启状态 SHOW VARIABLES LIKE ‘log_bin’; 如果未开启,修改配置my.ini 开启日志 安装目录配置my.ini(mysql8在data目录) log-binmysql-bin(开启日志并指定日志前缀ÿ…...
BiRefNet C++ TensorRT (二分类图像分割)
BiRefNet C TensorRT (二分类图像分割) 利用TensorRT和CUDA的双边参考网络(BiRefNet)的高性能c实现,针对实时高分辨率二分类图像分割进行了优化。 BiRefNet c TENSORRT旨在有效地在GPU上运行双边参考分割任务。通过利…...
蓝桥杯篇---IAP15F2K61S2矩阵键盘
文章目录 前言简介矩阵键盘的工作原理1.行扫描2.检测列状态3.按键识别 硬件连接1.行线2.列线 矩阵键盘使用步骤1.初始化IO口2.扫描键盘3.消抖处理4.按键识别 示例代码:4x4矩阵键盘扫描示例代码:优化后的矩阵键盘扫描注意事项1.消抖处理2.扫描频率3.IO口配…...
