FloodFill算法---BFS

目录

一、前言

二、算法模板套路

2.1 创建所需的全局变量:

2.2 BFS模板:

2.3 细节处理:

三、例题练习

3.1 例题1:图像渲染

3.2 例题2:岛屿数量

3.3 例题3:岛屿的最大面积

3.4 例题4:被围绕的区域


一、前言

在这之前我们已经学习了如何使用 DFS 解决 FloodFill 算法,如果有友友对 FloodFill 算法不太熟悉的话可以先看看我之前写的文章:FloodFill算法---DFS。里面详细介绍了什么是FloodFill算法和如何使用DFS来解决。通常 FloodFill 算法使用 DFS 或者 BFS 都可以,DFS 的代码会简洁一些,但是 BFS 可以用来解决最短路问题拓扑排序。所以本文章可以说是为了后续使用 BFS 解决最短路问题和拓扑排序打下基础。

• 关于BFS的遍历特性:若初始点为左上角,遍历特性如下图所示。

二、算法模板套路

2.1 创建所需的全局变量:

最好设置为静态,因为非静态只有在leetcode上才行,在竞赛中都是要我们自己写Main类的因为main是静态方法所以在方法外面的全局变量要设置为静态的才能被main方法调用。

static boolean[][] vis;//( 不一定要有)static int[ ] dx = {0 , 0 , 1 , -1 };static int[ ] dy = {1 , -1 , 0 , 0 };

• vis这个布尔类型数组来标记我们已经走过的路,防止重复走导致死循环:

还有一种可以不用创建 vis 来标记,直接修改原来数据的值,这个如果是在面试的时候要问一下面试官,原来数组的数值是否可以修改。

• 利用dx,dy 来实现上下左右移动(如果是8个方向的也行):

for(int k = 0;k < 4;k++){int x = i + dx[k];int y = j + dy[k];
}

 如果是 8 个方向的话可以先画出下图。

在把黄色对应的8个位置写入到dx和dy中。例如:

下面这个例子是从上到下,从左到右写的。

static int[] dx = {-1,-1,-1,0,0,1,1,1};
static int[] dy = {-1,0,1,-1,1,-1,0,1};

2.2 BFS模板:

我们利用 int[ ]来存储坐标。

• 至于要不要回溯,要根据题目要求什么来进行决定。

• x >= 0 && x < n && y >= 0 && y < m 这个可以说是默写了,因为这就是防止越界,每道题目都是这么写的。

public void bfs(char[][] grid, int i, int j) {Queue<int[]> queue = new LinkedList<>();queue.add(new int[] { i, j });while (!queue.isEmpty()) {int[] tmp = queue.poll();int a = tmp[0];int b = tmp[1];vis[a][b] = true;///1for (int k = 0; k < 4; k++) {int x = a + dx[k];int y = b + dy[k];if(x >= 0 && x < n && y >= 0 && y < m && !vis[x][y]){queue.add(new int[]{x,y});vis[x][y] = true;///2}}}}

2.3 细节处理:

不知道大家有没有注意到在模板那里,我在代码里标记了1和2,现在我要问问友友们,2处的代码能否省略?

答:不能省略。因为如果不加上代码2的话,有些节点会重复进入,导致代码超时(这个要想清楚,因为我当时没有代码2,检查代码检查半天才找到😭😭😭)。友友们在学完下面几个例题后可以去  岛屿数量 上面试一下。

如果疑惑哪个元素会被重复进入,可以看看下图(有点丑😭),蓝色元素会被两个红色元素扩散重复进入。如果加上代码 2 就不会有这种情况。

三、例题练习

3.1 例题1:图像渲染

• 题目链接:图像渲染

• 问题描述:

有一幅以 m x n 的二维整数数组表示的图画 image ,其中 image[i][j] 表示该图画的像素值大小。

你也被给予三个整数 sr ,  sc 和 newColor 。你应该从像素 image[sr][sc] 开始对图像进行 上色填充 。

为了完成 上色工作 ,从初始像素开始,记录初始坐标的 上下左右四个方向上 像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应 四个方向上 像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为 newColor 。

最后返回 经过上色渲染后的图像 

• 解题思路:

可以利用深搜(DFS)或者宽搜(BFS),遍历到与该点相连的所有像素相同的点,然后将其修改成指定的像素即可。因为这个可以直接在原来数组上修改,那么我们就不用创建 vis 来标记我们已经走过的路,由于本文章主要讲解 BFS 所以本题采用 BFS 来进行解决。最后一个小优化,如果要修改的值和原来的值相同,那么直接返回即可。

• 代码编写:

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) {if(image[sr][sc] == color){//处理边界情况return image;}int n = image.length;int m = image[0].length;int prev = image[sr][sc];Queue<int[]> queue = new LinkedList<>();queue.add(new int[]{sr,sc});//创建队列while(!queue.isEmpty()){int[] tmp = queue.poll();int i = tmp[0],j = tmp[1];image[i][j] = color;for(int k = 0;k < 4;k++){int x = i + dx[k];int y = j + dy[k];if(x >= 0 && x < n && y >= 0 && y < m && image[x][y] == prev){queue.offer(new int[]{x,y});}}}return image;}
}

3.2 例题2:岛屿数量

• 题目链接:岛屿数量

• 问题描述:

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

• 解题思路:

遍历整个矩阵,每次找到一块陆地的时候,岛屿数量 + 1,并且将这个陆地相连的所有陆地,全都修改,这样我们下次遍历到这里就不会影响最终的结果。当我们遍历完全部的矩阵的时候,岛屿数量也就找到了。

• 代码编写:

我们直接在原数据上修改,不用 vis 了。

class Solution {int[] dx = { 0, 0, 1, -1 };int[] dy = { 1, -1, 0, 0 };int n;int m;public int numIslands(char[][] grid) {int count = 0;// 最后统计岛屿数量n = grid.length;m = grid[0].length;for (int i = 0; i < n; i++) {for (int j = 0; j < m; j++) {if (grid[i][j] == '1') {//找到陆地bfs(grid, i, j);//标记count++;}}}return count;}public void bfs(char[][] grid, int i, int j) {Queue<int[]> queue = new LinkedList<>();queue.add(new int[] { i, j });while (!queue.isEmpty()) {int[] tmp = queue.poll();int a = tmp[0];int b = tmp[1];grid[a][b] = '2';///1for (int k = 0; k < 4; k++) {int x = a + dx[k];int y = b + dy[k];if(x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == '1'){queue.add(new int[]{x,y});grid[x][y] = '2';///2}}}}
}

如果没有代码块 2 就会出现下面这种情况:超时啦!

 

3.3 例题3:岛屿的最大面积

• 题目链接:岛屿的最大面积

• 问题描述:

给你一个大小为 m x n 的二进制矩阵 grid 。

岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。

岛屿的面积是岛上值为 1 的单元格的数目。

计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。

• 解题思路:

遍历整个矩阵,每当遇到一块土地的时候,就用深搜或者宽搜将与这块土地相连的整个岛屿的面积计算出来。 然后在搜索得到的所有的岛屿面积求一个最大值即可。 在搜索过程中,为了防止搜到重复的土地。也可以将原始矩阵的 1 修改成 2,当然我们也可以使用 vis 数组来保存我们走过的路。

• 代码编写:

class Solution {int n,m;int[] dx = {0,0,1,-1};int[] dy = {1,-1,0,0};public int maxAreaOfIsland(int[][] grid) {int max = 0;n = grid.length;m = grid[0].length;for(int i = 0;i < n;i++){for(int j = 0;j < m;j++){if(grid[i][j] == 1){max = Math.max(bfs(grid,i,j),max);//找出最大面积}}}return max;}public int bfs(int[][] grid,int i,int j){Queue<int[]> queue = new LinkedList<>();queue.offer(new int[]{i,j});int count = 1;while(!queue.isEmpty()){int[] tmp = queue.poll();int a = tmp[0],b = tmp[1];grid[a][b] = 2;for(int k = 0;k < 4;k++){int x = a + dx[k];int y = b + dy[k];if(x >= 0 && x < n && y >= 0 && y < m && grid[x][y] == 1){count++;queue.offer(new int[]{x,y});grid[x][y] = 2;//直接修改原数组的值即可。}}}return count;//返回岛屿的数量}
}

3.4 例题4:被围绕的区域

• 题目链接:被围绕的区域

• 问题描述:

给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。

• 解题思路:

我们可以发现直接做难度还是挺大的,要处理的边界和各种条件还是比较多的,这里我们采用一种正难则反的思路来解决这道问题。

1. 先处理边界上的 O 区域,因为这个 O 一定不会是被围绕的,所以遍历边界来一次搜索即可。

2. 扫描矩阵,进行还原。

这题我们采用 vis 来标记我们走过的路。

• 代码编写:

class Solution {boolean[][] vis;int[] dx = {0,0,1,-1};int[] dy = {1,-1,0,0};int n,m;public void solve(char[][] board) {n = board.length;m = board[0].length;vis = new boolean[n][m];//遍历边界for(int i = 0;i < m;i++){//第一行if(board[0][i] == 'O'){bfs(board,0,i);}//最后一行if(board[n - 1][i] == 'O'){bfs(board,n - 1,i);}}for(int i = 0;i < n;i++){//第一列if(board[i][0] == 'O'){bfs(board,i,0);}//最后一列if(board[i][m - 1] == 'O'){bfs(board,i,m - 1);}}//还原矩阵for(int i = 0;i < n;i++){for(int j = 0;j < m;j++){if(board[i][j] == 'O' && !vis[i][j]){board[i][j] = 'X';}}}}public void bfs(char[][] board,int i,int j){vis[i][j] = true;Queue<int[]> queue = new LinkedList<>();queue.offer(new int[]{i,j});while(!queue.isEmpty()){int[] tmp = queue.poll();int a = tmp[0];int b = tmp[1];for(int k = 0;k < 4;k++){int x = a + dx[k];int y = b + dy[k];if(x >= 0 && x < n && y >= 0 && y < m && board[x][y] == 'O' && !vis[x][y]){queue.offer(new int[]{x,y});vis[x][y] = true;}}}}
}

• 总结:BFS 来解决 FloodFill 类问题的模板是比较固定的,希望友友们要掌握好,因为我们后续还要利用 BFS 来解决最短路问题和拓扑排序。算法模板里面的细节处理一定要想清楚,其他的其实和之前 DFS 解决这类问题是一样的。

结语:

其实写博客不仅仅是为了教大家,同时这也有利于我巩固知识点,和做一个学习的总结,由于作者水平有限,对文章有任何问题还请指出,非常感谢。如果大家有所收获的话还请不要吝啬你们的点赞收藏和关注,这可以激励我写出更加优秀的文章。

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

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

相关文章

人工智能应用正在改变我们的生活

在这个AI蓬勃发展的时代&#xff0c;你如何使用人工智能&#xff1f;如果您认为还没有&#xff0c;请再想一想。人工智能已经为我们的许多日常活动提供了动力&#xff0c;尽管您可能还没有有意将其用作工具&#xff0c;但这种情况可能会在不久的将来发生变化。随着顶尖科技公司…

如何更换远程服务器的Python版本

目录 前言 正文 尾声 &#x1f52d; Hi,I’m Pleasure1234&#x1f331; I’m currently learning Vue.js,SpringBoot,Computer Security and so on.&#x1f46f; I’m studying in University of Nottingham Ningbo China&#x1f4eb; You can reach me by url below:My Blo…

简单的mysql主从复制搭建

文章目录 准备工作用Docker安装MySQL主库配置【192.168.13.32】从库配置【192.168.13.108】小结 准备工作 用虚拟机提前准备两台服务器&#xff0c;并且在服务器中分别安装好MySQL&#xff0c;服务器的信息如下&#xff1a; 数据库IP主节点192.168.13.32从节点192.168.13.108…

IDEA终端环境配置

Idea如何配置终端&#xff1b; 第一步&#xff1a;找到我的电脑&#xff0c;右击——属性——高级系统设置——环境变量 先配置path: 在后面加入&#xff1a;C:\Program Files (x86)\Java\jdk1.7.0_75\bin&#xff08;每个人放置jdk的位置不同。&#xff09; 新建classpath:…

【MySQL数据库】初步认识数据库,实现基本操作

在信息爆炸的今天&#xff0c;数据无处不在&#xff0c;它们构成了互联网世界的基石。但数据本身若未经有效组织和管理&#xff0c;就如同散落在沙滩上的珍珠&#xff0c;难以发挥其真正的价值。这时&#xff0c;“数据库”这一概念便如同一根线&#xff0c;将这些珍珠串联起来…

【Redis】Redis 主从集群(一)

为了避免 Redis 的单点故障问题&#xff0c;可以搭建一个 Redis 集群&#xff0c;将数据备份到集群中的其它节点上。若一个 Redis 节点宕机&#xff0c;则由集群中的其它节点顶上 1.主从集群搭建 Redis 的主从集群是一个“一主多从”的读写分离集群。集群中的 Master 节点负责…

数字人解决方案——AniPortrait音频驱动的真实肖像动画合成

概述 在当今数字化时代&#xff0c;将静态图像和音频素材转化为动态、富有表现力的肖像动画&#xff0c;已经成为游戏、数字媒体、虚拟现实等多个领域的重要技术。然而&#xff0c;开发人员在创建既具有视觉吸引力又能保持时间一致性的高质量动画框架方面面临着巨大挑战。其中…

k8s endpoint

Endpoint Service 并不是和 pod 直接相连的&#xff0c;Endpoint 介于两者之间。Endpoint 资源就是暴露一个服务的 IP 地址和端口的列表。 虽然在 spec 服务中定义了 pod 选择器&#xff0c;但在重定向传入连接时不会直接使用它。选择器用于构建 IP 和端口列表&#xff0c;然…

优思学院:精益六西格玛如何影响企业文化?

精益六西格玛&#xff08;Lean Six Sigma&#xff09;是一种在优化生产过程、提高效率、减少浪费的管理方法论。其影响远不止于生产线或质量控制部门&#xff0c;实际上&#xff0c;精益六西格玛的实施可以深刻影响企业文化的各个层面&#xff0c;從而令企業獲得真正最大的成功…

【JavaScript超详细的学习笔记-下】JavaScrip超详细的学习笔记,共27部分,12多万字,学习js不错的选择,内容超详细

想要获取笔记的可以点击下面链接获取&#xff0c;或者私信我 ** JavaScript超详细的学习笔记&#xff0c;点击我获取 13&#xff0c;闭包 13-1 闭包 闭包是指有权访问另一个函数作用域中的变量的函数&#xff1b;其本质就是在一个函数内部创建另一个内部函数&#xff1b;并…

基于若依的开源网盘系统

简介 在线网盘系统&#xff0c;使用了DFA算法&#xff0c;实现了文件夹的创建与修改&#xff0c;多级目录&#xff0c;很正常的文件夹一样&#xff0c;支持所有文件上传&#xff0c;并按文件类型分类&#xff0c;支持文件删除&#xff0c;回收站管理&#xff0c;恢复与彻底删除…

低空经济:无人机竞赛详解

无人机竞赛市场近年来呈现出蓬勃发展的态势&#xff0c;其市场价值不仅体现在竞赛本身&#xff0c;还体现在推动无人机技术创新、拓展应用场景以及促进产业链发展等多个方面。 一、比赛项目介绍 无人机竞赛通常分为多个项目&#xff0c;包括竞速赛、技巧赛、航拍赛等。每个项目…

HR人才测评:自控能力与岗位胜任力素质测评

自控能力是什么&#xff1f; 自控能力可以解释为自我控制的能力&#xff0c;指一个人在应对人事物突发事件时&#xff0c;及时调整进行的自我控制的表现&#xff0c;它是实行自我支配的一种能力&#xff0c;在能进行自主支配时&#xff0c;一个人就成熟不少了&#xff0c;也可以…

优选算法——双指针1

双指针 常⻅的双指针有两种形式&#xff0c;⼀种是对撞指针&#xff0c;⼀种是左右指针。 对撞指针&#xff1a;⼀般⽤于顺序结构中&#xff0c;也称左右指针。 对撞指针从两端向中间移动。⼀个指针从最左端开始&#xff0c;另⼀个从最右端开始&#xff0c;然后逐渐往中间逼 近…

MySQL-InnoDB数据存储结构

1、存储结构-页 索引结构提供了高效的索引方式&#xff0c;索引信息以及数据记录都保存在数据文件或索引文件中&#xff08;本质存储在页结构中&#xff09; 1.1、磁盘与内存交互的基本单位&#xff1a;页 在InnoDB中将数据划分为若干页&#xff0c;页的默认大小为&#xff…

webpack并行构建示例:

由于js的单线程特性&#xff0c;文件和任务时 要等待一个任务执行完成后执行下一个任务&#xff0c;但在实际开发中&#xff0c;很多任务是可以并行执行的&#xff08;如同时处理多个不同js文件或同事压缩多张图片&#xff09;&#xff0c;一些loader和插件&#xff08;thread-…

【数据结构】解密链表之旅(单链表篇)

前言 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我想让大家知道…

自制无感无刷电机驱动板

自制无感无刷电机驱动板 分别测试了基于C251的STC32G单片机、Arduino AVR的ATmega328PB、以及ARM的ST32F103单片机。 &#x1f9f2;测试转动效果 ✒目前市面上开源的有关无刷电机的项目数不胜数&#xff0c;其控制原理都大同小异&#xff0c;在没有领透其技术要领情况下&#x…

苍穹外卖项目---------收获以及改进(9-12)

①Spring Task-------实现系统定时任务 概念&#xff1a; 应用场景&#xff1a; 使用步骤&#xff1a; 实现订单超时和前一天派送中的订单的自动任务处理&#xff1a; Component Slf4j public class Mytask {Autowiredprivate OrderServiceimpl orderServiceimpl;/*** 处理订…

yarn 安装以及报错处理

前一种报错是由于没有安装yarn导致的&#xff0c;使用以下命令即可安装&#xff1a; npm install -g yarn 如果成功安装&#xff0c;将显示Yarn的版本号。 yarn --version 第二种报错是因为系统上的执行策略限制导致的。执行策略是一种安全功能&#xff0c;用于控制在计算机…