【BFS】《BFS 攻克 FloodFill:填平图形世界的技术密码》

文章目录

  • 前言
  • 例题
    • 一、 图像渲染
    • 二、 岛屿数量
    • 三、岛屿的最大面积
    • 四、被围绕的区域
  • 结语


前言

在这里插入图片描述

什么是BFS?

BFS(Breadth - First Search)算法,即广度优先搜索算法,是一种用于图或树结构的遍历算法。以下是其详细介绍:
算法原理:从给定的起始顶点开始,首先访问起始顶点,然后依次访问与起始顶点相邻的所有未被访问过的顶点,接着再以这些相邻顶点为基础,访问它们相邻的未访问顶点,以此类推,直到遍历完所有可达顶点或找到目标顶点。可以想象成以起始顶点为中心,一层一层地向外扩展访问。
实现方式:通常使用队列(Queue)数据结构来实现。先将起始顶点加入队列,然后不断取出队列头部的顶点进行访问,并将其未访问的相邻顶点加入队列,直到队列为空。
应用场景:常用于寻找图中两个顶点之间的最短路径、判断图的连通性、求解迷宫问题等。例如,在一个社交网络中,要查找从某个用户到另一个用户的最短关系链,就可以使用 BFS 算法。

FloodFill算法是什么问题呢?

问题描述:给定一个二维数组(可以表示图像的像素矩阵等),以及一个起始位置(种子点),还有要填充的颜色或值。算法的任务是从种子点开始,将与种子点相连通的具有相同颜色或值的区域,用新的颜色或值进行填充。例如,在图像编辑软件中,当使用油漆桶工具填充一个封闭区域时,就是 FloodFill 算法在起作用。

下面本篇文章将通过几个例题,带大家深入了解BFS和FloodFill问题

例题

一、 图像渲染

  1. 题目链接: 图像渲染
  2. 题目描述:

有⼀幅以 m x n 的⼆维整数数组表⽰的图画 image ,其中 image[i][j] 表⽰该图画的像素值⼤⼩。 你也被给予三个整数 sr , sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行上色填充 。
为了完成 上色⼯作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同 的相连像素点,接着再记录这四个⽅向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐 标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。 最后返回 经过上⾊渲染后的图像 。
示例1:
在这里插入图片描述输⼊: image = [[1,1,1],[1,1,0],[1,0,1]],sr = 1, sc = 1, newColor = 2 输出: [[2,2,2],[2,2,0],[2,0,1]]
解析: 在图像的正中间,(坐标(sr,sc)=(1,1)),在路径上所有符合条件的像素点的颜⾊都被更改成
注意,右下角的像素没有更改为 2,因为它不是在上下左右四个⽅向上与初始点相连的像素点
示例 2:
输⼊: image = [[0,0,0],[0,0,0]], sr = 0, sc = 0, newColor = 2 输出: [[2,2,2],[2,2,2]]

  1. 算法思路:
    初始化:
    首先记录起始像素image[sr][sc]的原始颜色originalColor。
    创建一个队列queue,用于存储待处理的像素点。将起始像素点(sr, sc)加入队列。
    开始搜索:
    当队列不为空时,取出队列头部的像素点(x, y)。
    检查当前像素点(x, y)的颜色是否等于originalColor,如果不等于,则跳过该点(因为该点不属于需要填充的区域)。
    如果当前像素点的颜色等于originalColor,则将该像素点的颜色修改为color。
    然后检查当前像素点的上下左右四个相邻像素点(x - 1, y)、(x + 1, y)、(x, y - 1)、(x, y + 1):
    确保相邻像素点在图像范围内(即0 <= x’ < m且0 <= y’ < n,其中x’和y’是相邻像素点的坐标)。
    确保相邻像素点的颜色等于originalColor(因为只有颜色相同的像素点才属于需要填充的区域)。
    如果满足上述条件,则将相邻像素点加入队列,等待后续处理。
    结束条件:当队列为空时,说明所有需要填充的像素点都已经处理完毕,此时返回修改后的图像image。

  2. 代码示例:

class Solution {int[] dx = {0,0,1,-1};int[] dy = {1,-1,0,0};public int[][] floodFill(int[][] image, int sr, int sc, int color) {int prev = image[sr][sc];if(prev==color) return image;int m = image.length;int n = image[0].length;Queue<int[]> q = new LinkedList<>();q.add(new int[]{sr,sc});while(!q.isEmpty()){int[] t = q.poll();int a = t[0],b = t[1];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]==prev){q.add(new int[]{x,y});}}}        return image;}
}

二、 岛屿数量

  1. 题目链接:岛屿数量
  2. 题目描述:

给你⼀个由 ‘1’(陆地)和 ‘0’(水)组成的的⼆维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由⽔平⽅向和/或竖直⽅向上相邻的陆地连接形成。 此外,你可以假设该网格的四条边均被水包围。
⽰例 1: 输⼊:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
示例 2:
输入:
grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]输出:3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 ‘0’ 或 ‘1’

  1. 算法思路:
    遍历整个矩阵,每次找到「⼀块陆地」的时候:
    • 说明找到「⼀个岛屿」,记录到最终结果 ret 里面;
    • 并且将这个陆地相连的所有陆地,也就是这块「岛屿」,全部「变成海洋」。这样的话,我们下次遍历到这块岛屿的时候,它「已经是海洋」了,不会影响最终结果。
    • 其中「变成海洋」的操作,可以利用「深搜」和「宽搜」解决,其实就是上述图像渲染 这道题~

  2. 代码示例:

class Solution {int[] dx={0,0,-1,1};int[] dy = {1,-1,0,0};int  m,n;boolean[][] vis = new boolean[301][301];public int numIslands(char[][] grid) {m = grid.length;n = grid[0].length;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);}}}return ret;}public void bfs(char[][] grid,int i  ,int j){Queue<int[]> q = new LinkedList<>();q.add(new int[]{i,j});vis[i][j] =true;while(!q.isEmpty()){int[] t = q.poll();int a = t[0],b = t[1];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' && !vis[x][y]){q.add(new int[]{x,y});vis[x][y] = true;}}}}
}

三、岛屿的最大面积

  1. 题目链接:岛屿的最大面积
  2. 题目描述:

给你⼀个大小为 m x n 的⼆进制矩阵 grid 。
岛屿是由⼀些相邻的 1 (代表⼟地) 构成的组合,这⾥的「相邻」要求两个 1 必须在 ⽔平或者竖直的 四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表⽔)包围着。
岛屿的面积是岛上值为 1 的单元格的数⽬。 计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
示例 1:
在这里插入图片描述
输⼊:
grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],
[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],
[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出:6
解释:答案不应该是 11 ,因为岛屿只能包含⽔平或垂直这四个方向上的 1 。
示例 2: 输⼊:
grid = [[0,0,0,0,0,0,0,0]]
输出:0
提⽰:m == grid.length
n == grid[i].length
1 <= m, n <= 50
grid[i][j] 为 0 或 1

  1. 算法思路:
    • 遍历整个矩阵,每当遇到⼀块⼟地的时候,就⽤「深搜」或者「宽搜」将与这块⼟地相连的「整个岛屿」的⾯积计算出来。
    • 然后在搜索得到的「所有的岛屿⾯积」求⼀个「最⼤值」即可。
    • 在搜索过程中,为了「防⽌搜到重复的⼟地」: ◦ 可以开⼀个同等规模的「布尔数组」,标记⼀下这个位置是否已经被访问过;
    ◦ 也可以将原始矩阵的 1 修改成 0 ,但是这样操作会修改原始矩阵。

  2. 代码示例:

class Solution {int m ,n;int[] dx = {0,0,1,-1};int[] dy = {1,-1,0,0};boolean[][] vis = new boolean[51][51];public int maxAreaOfIsland(int[][] grid) {m = grid.length;n = grid[0].length;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 =  Math.max(ret,bfs(grid,i,j));}}}return ret;}public int bfs(int[][] grid,int i ,int j){int count = 0;Queue<int[]> q = new LinkedList<>();q.add(new int[]{i,j});vis[i][j] = true;count++;while(!q.isEmpty()){int[] t = q.poll();int a = t[0],b = t[1];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 &&!vis[x][y]){q.offer(new int[]{x,y});vis[x][y] = true;count++;}}}return count;}
}

四、被围绕的区域

  1. 题目链接:被围绕的区域
  2. 题目描述

给你⼀个 m x n 的矩阵 board ,由若⼲字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域 ⾥所有的 ‘O’ 用’X’ 填充。
示例 1:
在这里插入图片描述
输⼊:board = [[“X”,“X”,“X”,“X”],[“X”,“O”,“O”,“X”],[“X”,“X”,“O”,“X”],[“X”,“O”,“X”,“X”]]
输出:[[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“X”,“X”,“X”],[“X”,“O”,“X”,“X”]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上,或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
示例 2:
输入:board = [[“X”]]
输出:[[“X”]]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 200
board[i][j] 为 ‘X’ 或 'O

  1. 解法:
    算法思路: 正难则反。 可以先利用 bfs 将与边缘相连的 ‘0’ 区域做上标记,然后重新遍历矩阵,将没有标记过的 '0’修改成 ‘X’ 即可。

  2. 代码示例:

   class Solution {int[] dx = {0, 0, 1, -1};int[] dy = {1, -1, 0, 0};int m, n;public void solve(char[][] board) {m = board.length;n = board[0].length;// 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') board[i][j] = 'X';else if (board[i][j] == '.') board[i][j] = 'O';}public void bfs(char[][] board, int i, int j) {Queue<int[]> q = new LinkedList<>();q.add(new int[]{i, j});board[i][j] = '.';while (!q.isEmpty()) {int[] t = q.poll();int a = t[0], b = t[1];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') {board[x][y] = '.';q.add(new int[]{x, y});}}}}}

结语

本文到这里就结束了,主要介绍了利用宽搜解决FloodFill算法问题,并通过例题深化了代码步骤,本篇文章题目十分考验代码能力,大家一定要自己尝试哦!

以上就是本文全部内容,感谢各位能够看到最后,创作不易,希望大家多多支持!

最后,大家再见!祝好!我们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/75515.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux安装MySQL数据库并使用C语言进行数据库开发

目录 一、前言 二、安装VMware运行Ubuntu 1.安装VMware 2.使用VMware打开Ubuntu 三、配置VMware使用网卡 1.添加NAT网卡 四、Linux下安装MySQL数据库 五、安装MySQL开发库 六、演示代码 sql_connect.c sql_connect.h main.c中数据库相关代码 结尾 一、前言 由于最…

ROS2 部署大语言模型节点

4GB GPU的DeepSeek-Coder 1.3B模型&#xff0c;并且它已经被量化或优化过。以下是具体的步骤&#xff1a; 安装必要的依赖项&#xff1a; pip install transformers torch grpcio googleapis-common-protos创建一个新的ROS 2包&#xff1a; cd ~/ros2_ws/src ros2 pkg creat…

本人设计的最完全的光压发电机模型

双螺旋转子光压发电机结构模型 作者&#xff1a;龚仕成 单位&#xff1a;四川水利职业技术学院电力工程系 日期&#xff1a;2024年3月25日 摘要 本文提出了一种基于梯形螺旋沟槽多层复合材料转子的光压发电机结构模型&#xff0c;通过光-机-电协同设计实现高效能量转换。通…

六十天Linux从0到项目搭建(第五天)(file、bash 和 shell 的区别、目录权限、默认权限umask、粘滞位、使用系统自带的包管理工具)

1. file [选项] 文件名 用于确定文件类型的实用工具。它会通过分析文件内容&#xff08;而不仅仅是文件扩展名&#xff09;来判断文件的实际类型 示例输出解析 $ file /bin/bash /bin/bash: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, i…

基于大模型预测的初治菌阳肺结核诊疗方案研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 二、初治菌阳肺结核概述 2.1 疾病定义与病理机制 2.2 流行病学特征 2.3 传统诊疗方法与局限性 三、大模型在初治菌阳肺结核预测中的应用原理 3.1 大模型技术简介 3.2 数据收集与预处理 3.3 模型构建与训练 3.4 模型…

常见中间件漏洞之一 ----【Tomcat】

中间件Tomcat介绍&#xff1a; tomcat是⼀个开源⽽且免费的jsp服务器&#xff0c;默认端⼝ : 8080&#xff0c;属于轻量级应⽤服务器。它可以实现 JavaWeb程序的装载&#xff0c;是配置JSP&#xff08;Java Server Page&#xff09;和JAVA系统必备的⼀款环境。 在历史上也披露…

GoogleNet的简易实现

这里使用GooleNet对MNIST手写数据集进行分类&#xff0c;最后的效果达到了在测试集98%的准确率。这里关于该网络的细节可以在网络上搜索到&#xff0c;相关原理也可以搜索到&#xff0c;这里仅展示网络的代码实现&#xff0c;这里是基于pytorch实现的&#xff0c;详细的代码如下…

javaweb自用笔记:Mybatis

目录 mybatis 配置sql书写提示 JDBC 数据库连接池 lombok mybatis 只需要定义Mapper接口就好&#xff0c;不需要有实现类&#xff0c;因为框架底层会自动生成实现类 配置sql书写提示 JDBC 数据库连接池 lombok XML映射文件 动态SQL

Rust从入门到精通之精通篇:22.Unsafe Rust 详解

Unsafe Rust 详解 在 Rust 的设计哲学中,安全性是核心原则之一。Rust 的所有权系统、借用检查器和类型系统共同保证了内存安全和线程安全。然而,有些底层操作无法通过 Rust 的安全检查机制进行验证,这就是 unsafe Rust 存在的原因。在本章中,我们将深入探讨 unsafe Rust,…

比手动备份快 Iperius全自动加密备份,NAS/云盘/磁带机全兼容

IperiusBackupFull是一款专为服务器和工作站设计的备份解决方案&#xff0c;它同时也是一款针对Windows 7/8/10/11/Server系统的简洁且可靠的备份软件。该软件支持增量备份、数据同步以及驱动器镜像&#xff0c;确保能够实现完全的系统恢复。在备份存储方面&#xff0c;Iperius…

deepseek实战教程-第六篇查找源码之仓库地址与deepseek-R1、deepseek-LLM仓库内容查看

上一篇讲了支持deepseek的模型应用的本地安装和部署以及使用。再上一篇讲解了deepseek提供的开放api,便于开发者基于deepseek提供的接口来编写属于自己的业务应用程序。但是前面几篇我们都是在用模型,我们知道deepseek是开源的,那么deepseek的源码在哪里,具体源码是什么样的…

ES 加入高亮设置

searchTextQueryOne new MatchQuery.Builder().field(searchFieldOne).query(searchText).build();// 帮助中心文档切分 只查询6条Integer finalTopK 10;List<String> newReturnFileds returnFields;newReturnFileds.add("kid"); // 需要返回kidHighlight h…

mapbox进阶,添加鹰眼图控件

👨‍⚕️ 主页: gis分享者 👨‍⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍⚕️ 收录于专栏:mapbox 从入门到精通 文章目录 一、🍀前言1.1 ☘️mapboxgl.Map 地图对象1.2 ☘️mapboxgl.Map style属性1.3 ☘️mapboxgl-minimap 鹰眼控件二、🍀添加…

亮数据爬取API爬取亚马逊电商平台实战教程

前言 在当今数据驱动的商业环境中&#xff0c;企业需要快速、精准地获取互联网上的公开数据以支持市场分析、竞品调研和用户行为研究。然而&#xff0c;传统的手动网页爬取方式面临着诸多挑战&#xff1a;IP封锁、验证码干扰、网站结构频繁变更&#xff0c;以及高昂的运维成本…

「Unity3D」使用C#获取Android虚拟键盘的高度

原理是&#xff1a;利用getWindowVisibleDisplayFrame方法&#xff0c;获取Android窗口可见区域的Rect&#xff0c;这个Rect剔除了状态栏与导航栏&#xff0c;并且在有虚拟键盘遮挡的时候&#xff0c;会剔除这个遮挡区域。 接着&#xff0c;Unity的safeArea也剔除了状态栏与导…

“城市超级智能体”落地,联想智慧城市4.0“功到自然成”

作者 | 曾响铃 文 | 响铃说 交通摄像头捕捉到车流量数据&#xff0c;进入一套“自动化”的城市整体管理体系中&#xff0c;交通路况信息、天气变化情况以及城市大型活动安排等看似分散的数据被整合&#xff0c;根据预测的路况精准调控交通信号灯&#xff0c;让自动驾驶清扫车…

每日总结3.24

第十届蓝桥杯大赛软件赛省赛C/C 大学 B 组 183.完全二叉树的权值&#xff08;找规律&#xff0c;临界值&#xff09; #include <bits/stdc.h> using namespace std; int a[1000005]; int main() { int m;int d; cin>>m; int sum;int maxn0; for(int i1;i&…

计算机复试面试

数据库 1.设计过程/设计步骤 1.需求分析&#xff1a;明确客户需求&#xff0c;确定系统边界&#xff0c;生成数据字典 2.概念结构设计&#xff1a;将用户需求抽象为概念模型&#xff0c;绘制e-r图 3.逻辑结构设计&#xff1a;将e-r图转化为dbms相符合的逻辑结构&#xff0c;db…

模型 拆屋效应

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。先过分后合理&#xff0c;易被接受。 1 拆屋效应的应用 1.1 高端手表销售案例 一、案例背景 在高端手表销售领域&#xff0c;销售人员面临顾客对价格敏感且购买决策谨慎的挑战。如何引导顾客接受较高…

Windows系统下Pycharm+Minianaconda3连接教程【成功】

0.引言 PycharmMinianaconda3开发组合的好处 优点类别具体优点描述环境管理便捷独立环境创建 环境复制与共享Miniconda3可创建多独立Python环境&#xff0c;支持不同版本与依赖&#xff0c;避免冲突。 能复制、分享环境配置&#xff0c;方便团队搭建相同开发环境。依赖管理高…