LeetCode200.岛屿数量

看完题目我还感觉这道题目有点难,没想到20分钟不到就完全靠自己给写出来了。我就是按照自己的想法来,我用一个等大的visit数组来表示grid数组中的这个元素是否被访问过(是否已经被判断了是不是岛屿)。

先用一个大的循环对grid数组遍历,去判断里面的元素grid[i][j]是不是一个岛屿。如果它是一个岛屿的话,就要把岛屿数量+1,并且要把和grid[i][j]相连的陆地全部算在这个岛屿中,所以要把和它相连的陆地的visit设置成true,下次遍历到这个点就直接跳过。

那么如何把grid[i][j]的相连的陆地的visit全部置为true呢,利用递归就可以了,用setVisit(char[][] grid, boolean[][] visit, int i, int j),grid数组和visit数组就是全局的grid数组和visit数组(如果把这两个数组定义在类里面就不用传这两个参了),i,j就是要进行置true的元素下标,先把visit[i][j]置为true,然后再递归调用setVist()方法把visit[i][j]的上下左右4个方向的visit置为true,当然不是直接置true,要进行判断,假设相邻位置是m,n,首先必须要m,n大于等于0小于length,其次grid[m][n]要等于1并且visit[m][n]要等于false,然后直接递归调用setVisit方法把visit[m][n]置为true,这样进行递归就会把与grid[i][j]相连的所有陆地都visit了,

那么如何判断grid[i][j]是不是岛屿呢?其实很简单,如果grid[i][j]是1并且它没有被visit过他就是岛屿,因为它如果没有被visit过只有两种可能,第一种是没有任何陆地和它相连所以它没有被visit,第二种是它是它所在的岛屿第一个被发现的陆地,以上两种情况都可以把它判定为岛屿给岛屿属灵加一,最后返回岛屿数量result即可,以下是我的代码:

class Solution {public int numIslands(char[][] grid) {int m = grid.length;int n = grid[0].length;boolean[][] visit = new boolean [m][n];int result=0;for(int i =0;i<m;i++){for(int j=0;j<n;j++){if(grid[i][j] == '1' && !visit[i][j]){result++;setVisit(grid, visit, i, j);}}}return result;}public void setVisit(char[][] grid, boolean[][] visit, int i, int j){visit[i][j] =true;if(i+1<visit.length && grid[i+1][j] == '1' && visit[i+1][j] == false)setVisit(grid, visit, i+1, j);if(j+1<visit[0].length && grid[i][j+1] == '1' && visit[i][j+1] == false)setVisit(grid, visit, i, j+1);if(i-1>=0 && grid[i-1][j] == '1' && visit[i-1][j] == false)setVisit(grid, visit, i-1, j);if(j-1>=0 && grid[i][j-1] == '1' && visit[i][j-1] == false)setVisit(grid, visit, i, j-1);}
}

看看官方题解的做法吧:

题解的方法一用的是深度优先搜索,和我的方法是一样的,只不过它没有用标记数组visit,而是直接再grid数组上把相连的陆地由1改成了0,以下是题解方法一的代码:

class Solution {void dfs(char[][] grid, int r, int c) {int nr = grid.length;int nc = grid[0].length;if (r < 0 || c < 0 || r >= nr || c >= nc || grid[r][c] == '0') {return;}grid[r][c] = '0';dfs(grid, r - 1, c);dfs(grid, r + 1, c);dfs(grid, r, c - 1);dfs(grid, r, c + 1);}public int numIslands(char[][] grid) {if (grid == null || grid.length == 0) {return 0;}int nr = grid.length;int nc = grid[0].length;int num_islands = 0;for (int r = 0; r < nr; ++r) {for (int c = 0; c < nc; ++c) {if (grid[r][c] == '1') {++num_islands;dfs(grid, r, c);}}}return num_islands;}
}

题解的方法二用的是广度优先搜索,如果gird[i][j]等于1就把它放到一个队列里面,然后不断的从队列中取出元素把grid置为0,每取出一个就把这个元素的上下左右放进队列(当然需要这些元素的grid为1),值得注意的是它放进队列的是这个元素在数组中的序号,也就是行号*每行的个数+列号,所以这个队列中的这个序号被取出来后会通过模运算算出行号和列号,方便找上下左右4个元素。以下是题解方法二的代码:

class Solution {public int numIslands(char[][] grid) {if (grid == null || grid.length == 0) {return 0;}int nr = grid.length;int nc = grid[0].length;int num_islands = 0;for (int r = 0; r < nr; ++r) {for (int c = 0; c < nc; ++c) {if (grid[r][c] == '1') {++num_islands;grid[r][c] = '0';Queue<Integer> neighbors = new LinkedList<>();neighbors.add(r * nc + c);while (!neighbors.isEmpty()) {int id = neighbors.remove();int row = id / nc;int col = id % nc;if (row - 1 >= 0 && grid[row-1][col] == '1') {neighbors.add((row-1) * nc + col);grid[row-1][col] = '0';}if (row + 1 < nr && grid[row+1][col] == '1') {neighbors.add((row+1) * nc + col);grid[row+1][col] = '0';}if (col - 1 >= 0 && grid[row][col-1] == '1') {neighbors.add(row * nc + col-1);grid[row][col-1] = '0';}if (col + 1 < nc && grid[row][col+1] == '1') {neighbors.add(row * nc + col+1);grid[row][col+1] = '0';}}}}}return num_islands;}
}

题解的方法三采用的是并查集的方法,这个方法有点复杂,先上代码:

class Solution {class UnionFind {int count;int[] parent;int[] rank;public UnionFind(char[][] grid) {count = 0;int m = grid.length;int n = grid[0].length;parent = new int[m * n];rank = new int[m * n];for (int i = 0; i < m; ++i) {for (int j = 0; j < n; ++j) {if (grid[i][j] == '1') {parent[i * n + j] = i * n + j;++count;}rank[i * n + j] = 0;}}}public int find(int i) {if (parent[i] != i) parent[i] = find(parent[i]);return parent[i];}public void union(int x, int y) {int rootx = find(x);int rooty = find(y);if (rootx != rooty) {if (rank[rootx] > rank[rooty]) {parent[rooty] = rootx;} else if (rank[rootx] < rank[rooty]) {parent[rootx] = rooty;} else {parent[rooty] = rootx;rank[rootx] += 1;}--count;}}public int getCount() {return count;}}public int numIslands(char[][] grid) {if (grid == null || grid.length == 0) {return 0;}int nr = grid.length;int nc = grid[0].length;int num_islands = 0;UnionFind uf = new UnionFind(grid);for (int r = 0; r < nr; ++r) {for (int c = 0; c < nc; ++c) {if (grid[r][c] == '1') {grid[r][c] = '0';if (r - 1 >= 0 && grid[r-1][c] == '1') {uf.union(r * nc + c, (r-1) * nc + c);}if (r + 1 < nr && grid[r+1][c] == '1') {uf.union(r * nc + c, (r+1) * nc + c);}if (c - 1 >= 0 && grid[r][c-1] == '1') {uf.union(r * nc + c, r * nc + c - 1);}if (c + 1 < nc && grid[r][c+1] == '1') {uf.union(r * nc + c, r * nc + c + 1);}}}}return uf.getCount();}
}

它是采用了一个内部类UnionFind,这个类有一个count属性,表示岛屿的个数,parent[]数组,大小就是giad的数组的大小,grid的每个元素都在parent中有对应的位置,也是采用序号的方式(行号*每行的个数+列号),比如grid[i][j]在parent中对应的下标就是parent[i*每行个数+j],它表示grid[i][j]有那个序号的元素连接而找到,通过

public int find(int i) {if (parent[i] != i) parent[i] = find(parent[i]);return parent[i];}

就可以找到序号i元素的最大祖先,然后通过

public void union(int x, int y) {int rootx = find(x);int rooty = find(y);if (rootx != rooty) {if (rank[rootx] > rank[rooty]) {parent[rooty] = rootx;} else if (rank[rootx] < rank[rooty]) {parent[rootx] = rooty;} else {parent[rooty] = rootx;rank[rootx] += 1;}--count;}}

rank是一个和gird等大的数组,它表示rank[序号]所在树的深度,

假设grid[i][j]的序号是x,他的相邻元素的序号是y,通过find方法分别找到x和y的根节点rootx和rooty,如果rootx和rooty不相等说明他们之前在两颗独立的树上,因为x和y是相邻的,所以他们其实在同一颗树上,所以他们的树的深度是两颗树深度最大的一个,大的那个root是小的root的parent;如果两颗树的深度相等,那么可以把其中一个root挂在另一个root的叶子上,那么树的深度就+1了,因为他们两个树之前是独立的,但其实他们是一起的也就是说之前count多加了一次,所以count要-1,

只要在numIslands中把grid的每个节点遍历一次,最后返回count即可。

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

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

相关文章

贝锐蒲公英X1解决远程访问NAS难题

由于经常在外出差和旅游&#xff0c;需要实现即使在外地也能远程登录回去家里的NAS去处理事情或传输文件&#xff0c;因此解决方案之一是搭建一个安全简易的个人私有云。 实施难度 &#xff08;1&#xff09;家庭网络无公网IP&#xff0c;且公网IP价格昂贵&#xff08;2&…

Django的ORM操作

文章目录 1.ORM操作1.1 表结构1.1.1 常见字段和参数1.1.2 表关系 2.ORM2.1 基本操作2.2 连接数据库2.3 基础增删改查2.3.1 增加2.3.2 查找2.3.4 删除2.3.4 修改 1.ORM操作 orm&#xff0c;关系对象映射&#xff0c;本质翻译的。 1.1 表结构 实现&#xff1a;创建表、修改表、…

Python用requests库采集充电桩LBS位置经纬度信息

这是一个使用Python的requests库来爬取网页内容的示例。首先&#xff0c;我们需要导入requests库。然后&#xff0c;我们需要定义一个函数来处理请求。在这个函数中&#xff0c;我们需要设置爬虫IP服务器的URL和端口号&#xff0c;然后使用requests.get来获取网页内容。最后&am…

GoF之代理模式

2023.11.12 代理模式是GoF23种设计模式之一&#xff0c;其作用是&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。在某些情况下&#xff0c;一个客户不想或者不能直接引用一个对象&#xff0c;此时可以通过一个称之为“代理”的第三者来实现间接引用。代理对象可以…

解决springboot接受buffer文件为null(从picgo上传buffer看springmvc处理过程)

1. 前言&#xff1a; picgo插件的简单开发 上篇文章我们简单写了picgo上传插件&#xff0c;但是当我们测试的时候&#xff0c;发现问题了&#xff0c;后端MultipartFile file接受到的文件为null。 2. 排查问题&#xff1a; 参考的文档 picgo api列表关于multipart form-data中…

链表OJ题【环形链表】(3)

目录 环形问题的思考 ❓Q1 ❓Q2 &#x1f642;Q2 ❓Q3 ❓Q4 8.环形链表 9.环形链表Ⅱ 今天接着链表的经典问题环形问题。大家一定要自己动手多写写。&#x1f642; 快慢指针&#xff08;保持相对距离/保持相对速度&#xff09;野指针考虑为NULL的情况带环链表&#x…

SpringBoot自动装配定义先后顺序失效原因极其解析

SpringBoot自动装配定义先后顺序失效原因极其解析 1、场景分析1.1、问题总结 2、使用AutoConfigureBefore、AutoConfigureAfter和AutoConfigureOrder注解指定加载顺序2.2、AutoConfigureXX注解失效原因总结 3、使用静态内部装配类提升加载顺序4、bean加载顺序规则 1、场景分析 …

矩阵起源加入 OpenCloudOS 操作系统开源社区,完成技术兼容互认证

近日&#xff0c;超融合异构云原生数据库 MatrixOne企业版软件 V1.0 完成了与 OpenCloudOS 的相互兼容认证&#xff0c;测试期间&#xff0c;整体运行稳定&#xff0c;在功能、性能及兼容性方面表现良好。 一、产品简介 矩阵起源 MatrixOrigin 致力于建设开放的技术开源社区和…

Nginx缓存基础

1 nginx缓存的流程 客户端需要访问服务器的数据时&#xff0c;如果都直接向服务器发送请求&#xff0c;服务器接收过多的请求&#xff0c;压力会比较大&#xff0c;也比较耗时&#xff1b;而如果在nginx缓存一定的数据&#xff0c;使客户端向基于nginx的代理服务器发送请求&…

Spring面试题:(五)Spring注解开发@Component,@Autowired,@Bean,@Configuration

Bean基本注解 spring提供注解的版本 Component注解替代bean标签 bean其它属性的相关注解&#xff1a; scope 替代scopelazy 替代lazy-initPostConstruct 替代init-methodPreDestroy 替代destroy-method 使用Component注解的前提是开启注解扫描 衍生注解Repository,Servi…

jdk安装

.概览 1.jdk下载 JDK(Java Development Kit) 是 Java 语言的软件开发工具包(SDK)。 安装JDK后&#xff0c;会在电脑中同时安装&#xff1a;java的运行环境jre 和 开发环境jdk。 安装 JDK时&#xff0c;不建议安装太旧或太新的版本。目前的最新版本是jdk9。目前jdk8比较稳定&am…

STM32 LED编程 GPIO的初始化(标准库)

实验的电路图介绍 实验的电路图类似于开漏接法 要初始化GPIOC接口 标准库的模板 GPIO的标准库编程接口 GPIO引脚的初始化 GPIO作为片上外设 每一个片上外设使用前一定要使能时钟 为什么要使能时钟&#xff1f;时钟是啥 时钟的使能 stm32的每一个片上外设都是时序电路 时序…

多数据源切换

多数据源切换 jdbcTemplate二级目录三级目录 jdbcTemplate使用切面mybatis层次的多数据源spring的dynamic自动注入 jdbcTemplate 二级目录 三级目录 项目中经常会有多个数据源&#xff0c;那么如何处理呢 有4种方法 准备&#xff1a; 创建两个数据库 CREATE SCHEMA test DE…

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…

GCC工具详解【Linux知识贩卖机】

很多人在喧嚣声中登场&#xff0c;也有少数人在静默中退出。 --单独中的洞见2 文章目录 简介程序到可执行文件链接动态链接和静态链接动态库和静态库动态库和静态库的打包打包静态库打包动态库选项 -static 总结 简介 GCC&#xff08;GNU Compiler Collection&#xff09; 是一…

计算机中丢失mfc140u.dll怎么解决

mfc140u.dll是一个Microsoft Visual C库文件&#xff0c;主要用于MFC&#xff08;Microsoft Foundation Class&#xff09;应用程序的开发。它包含了MFC应用程序所需的一些常用功能&#xff0c;如对话框、窗口、菜单等。当mfc140u.dll丢失时&#xff0c;可能会导致MFC应用程序无…

思科9300交换机使用USB进行升级ISO

一、下载ISO 一、网址 Software Download - Cisco Systems 二、找到型号 四、选择XE 软件 五、进行下载 二、COPY 进 U盘 一、、请注意&#xff01;如果你的U盘不是Fat32文件格式则交换机读取不了&#xff0c;请先格式化再复制文件。 二、下载后将 bin文件复制到U盘。 1.扩展…

idea Plugins 搜索不到插件

Settings — System Settings — HTTP Proxy&#xff0c;打开HTTP Proxy 页面&#xff0c;设置自动发现代理&#xff1a; 勾选Atuto-detect proxy settings&#xff0c;勾选Automatic proxy configuration URL&#xff0c;输入&#xff1a; https://plugins.jetbrains.com/id…

【Python】AppUI自动化—appium自动化元素定位、元素事件操作(17)下

文章目录 前言一.Appium 元素定位1.定位方式种类2.如何定位2.1 id定位2.2 className定位2.3 content-desc 定位2.4 Android Uiautomator定位4.1 text定位4.2 text模糊定位4.3 text正则匹配定位4.4 resourceId定位4.5 resourceId正则匹配定位4.6 className定位4.7 className正则…

No184.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…