[Leedcode][JAVA][第200题][岛屿数量][DFS][BFS][并查集]

【问题描述】 第200题 岛屿数量

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。示例 1:输入:
11110
11010
11000
00000
输出: 1
示例 2:输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

【解答思路】

1. 深度优先遍历

时间复杂度:O(N^2) 空间复杂度:O(N)

/*** 方法一:深度优先遍历*/
public class Solution {//           x-1,y//  x,y-1    x,y      x,y+1//           x+1,y// 方向数组,它表示了相对于当前位置的 4 个方向的横、纵坐标的偏移量,这是一个常见的技巧private static final int[][] directions = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};// 标记数组,标记了 grid 的坐标对应的格子是否被访问过private boolean[][] marked;// grid 的行数private int rows;// grid 的列数private int cols;private char[][] grid;public int numIslands(char[][] grid) {rows = grid.length;if (rows == 0) {return 0;}cols = grid[0].length;this.grid = grid;marked = new boolean[rows][cols];int count = 0;for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {// 如果是岛屿中的一个点,并且没有被访问过// 就进行深度优先遍历if (!marked[i][j] && grid[i][j] == '1') {count++;dfs(i, j);}}}return count;}// 从坐标为 (i,j) 的点开始进行深度优先遍历private void dfs(int i, int j) {marked[i][j] = true;// 得到 4 个方向的坐标for (int k = 0; k < 4; k++) {int newX = i + directions[k][0];int newY = j + directions[k][1];// 如果不越界、没有被访问过、并且还要是陆地if (inArea(newX, newY) && grid[newX][newY] == '1' && !marked[newX][newY]) {dfs(newX, newY);}}}// 封装成 inArea 方法语义更清晰private boolean inArea(int x, int y) {// 等于号不要忘了return x >= 0 && x < rows && y >= 0 && y < cols;}public static void main(String[] args) {Solution solution = new Solution();char[][] grid1 = {{'1', '1', '1', '1', '0'},{'1', '1', '0', '1', '0'},{'1', '1', '0', '0', '0'},{'0', '0', '0', '0', '0'}};int numIslands1 = solution.numIslands(grid1);System.out.println(numIslands1);char[][] grid2 = {{'1', '1', '0', '0', '0'},{'1', '1', '0', '0', '0'},{'0', '0', '1', '0', '0'},{'0', '0', '0', '1', '1'}};int numIslands2 = solution.numIslands(grid2);System.out.println(numIslands2);}
}
2. 广度优先遍历

时间复杂度:O(N) 空间复杂度:O(N)

import java.util.LinkedList;/*** 方法二:广度优先遍历*/
public class Solution2 {private int rows;private int cols;public int numIslands(char[][] grid) {//           x-1,y//  x,y-1    x,y      x,y+1//           x+1,yint[][] directions = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};rows = grid.length;if (rows == 0) {return 0;}cols = grid[0].length;boolean[][] marked = new boolean[rows][cols];int count = 0;for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {// 如果是岛屿中的一个点,并且没有被访问过// 从坐标为 (i,j) 的点开始进行广度优先遍历if (!marked[i][j] && grid[i][j] == '1') {count++;LinkedList<Integer> queue = new LinkedList<>();// 小技巧:把坐标转换为一个数字// 否则,得用一个数组存,在 Python 中,可以使用 tuple 存queue.addLast(i * cols + j);// 注意:这里要标记上已经访问过marked[i][j] = true;while (!queue.isEmpty()) {int cur = queue.removeFirst();int curX = cur / cols;int curY = cur % cols;// 得到 4 个方向的坐标for (int k = 0; k < 4; k++) {int newX = curX + directions[k][0];int newY = curY + directions[k][1];// 如果不越界、没有被访问过、并且还要是陆地,我就继续放入队列,放入队列的同时,要记得标记已经访问过if (inArea(newX, newY) && grid[newX][newY] == '1' && !marked[newX][newY]) {queue.addLast(newX * cols + newY);// 【特别注意】在放入队列以后,要马上标记成已经访问过,语义也是十分清楚的:反正只要进入了队列,你迟早都会遍历到它// 而不是在出队列的时候再标记// 【特别注意】如果是出队列的时候再标记,会造成很多重复的结点进入队列,造成重复的操作,这句话如果你没有写对地方,代码会严重超时的marked[newX][newY] = true;}}}}}}return count;}private boolean inArea(int x, int y) {// 等于号这些细节不要忘了return x >= 0 && x < rows && y >= 0 && y < cols;}public static void main(String[] args) {Solution2 solution2 = new Solution2();char[][] grid1 = {{'1', '1', '1', '1', '0'},{'1', '1', '0', '1', '0'},{'1', '1', '0', '0', '0'},{'0', '0', '0', '0', '0'}};int numIslands1 = solution2.numIslands(grid1);System.out.println(numIslands1);char[][] grid2 = {{'1', '1', '0', '0', '0'},{'1', '1', '0', '0', '0'},{'0', '0', '1', '0', '0'},{'0', '0', '0', '1', '1'}};int numIslands2 = solution2.numIslands(grid2);System.out.println(numIslands2);}
}
3. 并查集

public class Solution {

public int numIslands(char[][] grid) {int rows = grid.length;if (rows == 0) {return 0;}int cols = grid[0].length;int size = rows * cols;// 两个方向的方向向量(理解为向下和向右的坐标偏移)int[][] directions = {{1, 0}, {0, 1}};// +1 是认为虚拟的水域UnionFind unionFind = new UnionFind(size + 1);for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {if (grid[i][j] == '1') {for (int[] direction : directions) {int newX = i + direction[0];int newY = j + direction[1];if (newX < rows && newY < cols && grid[newX][newY] == '1') {unionFind.union(cols * i + j, cols * newX + newY);}}} else {// 如果不是陆地,所有的水域和一个虚拟的水域连接unionFind.union(cols * i + j, size);}}}// 减去那个一开始多设置的虚拟的水域return unionFind.count - 1;
}class UnionFind {private int[] parent;private int count;public UnionFind(int n) {this.count = n;parent = new int[n];for (int i = 0; i < n; i++) {parent[i] = i;}}/*** 返回索引为 p 的元素的根结点** @param p* @return*/public int find(int p) {// 在 find 的时候执行路径压缩while (p != parent[p]) {// 两步一跳完成路径压缩,这里是「隔代压缩」// 说明:「隔代压缩」和「按秩合并」选择一个实现即可,「隔代压缩」的代码量少,所以选它parent[p] = parent[parent[p]];p = parent[p];}return p;}public boolean connected(int p, int q) {int pRoot = find(p);int qRoot = find(q);return pRoot == qRoot;}public void union(int p, int q) {int pRoot = find(p);int qRoot = find(q);if (pRoot == qRoot) {return;}parent[qRoot] = pRoot;// 每次 union 以后,连通分量减 1count--;}
}

}

image.png

【总结】

1. 深度遍历
  • 递归
2. 广度遍历
  • 队列
  • 所有加入队列的结点,都应该马上被标记为 “已经访问”,否则有可能会被重复加入队列
3.并查集学习资料

https://liweiwei1419.gitee.io/leetcode-algo/leetcode-by-tag/union-find/

参考链接:https://leetcode-cn.com/problems/number-of-islands/solution/dfs-bfs-bing-cha-ji-python-dai-ma-java-dai-ma-by-l/

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

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

相关文章

python闯关_Day012

day012 用python实现信息卡管理及购物商城的项目 需求 #需求: 1 这是一个信用卡管理程序 2 用户手持信用卡购物&#xff0c;使用函数&#xff0c;按照软件开发规范 3 用户名密码存放于文件中&#xff0c;支持多用户登陆&#xff0c;使用json 4 程序启动&#xff0c;先登录或者…

[Leedcode][JAVA][第1248题][统计「优美子数组][找规律]

【问题描述】 1248. 统计「优美子数组」 给你一个整数数组 nums 和一个整数 k。如果某个 连续 子数组中恰好有 k 个奇数数字&#xff0c;我们就认为这个子数组是「优美子数组」。请返回这个数组中「优美子数组」的数目。 示例 1&#xff1a;输入&#xff1a;nums [1,1,2,1,1]…

[ubuntu setting]Change system language

1.Open the software "语言支持". ​ 2.Then select "English" lauguage, an apply to whole system. ​ 3.reboot system. [end]转载于:https://www.cnblogs.com/lizhuohui/p/10274356.html

http:(4):http请求方法

HTTP 消息结构 HTTP是基于客户端/服务端&#xff08;C/S&#xff09;的架构模型&#xff0c;通过一个可靠的链接来交换信息&#xff0c;是一个无状态的请求/响应协议。 一个HTTP"客户端"是一个应用程序&#xff08;Web浏览器或其他任何客户端&#xff09;&#xff…

[Leedcode][JAVA][第199题][二叉树的右视图][BFS][DFS][前中后序遍历]

【问题描述】199.二叉树的右视图 给定一棵二叉树&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。示例:输入: [1,2,3,null,5,null,4] 输出: [1, 3, 4] 解释:1 <---/ \ 2 3 <---\…

基于声音的击键信号识别

摘要 本文文章采用击键信号的短时能量及峰值片段的幅度及各个幅度对应的频率作为特征向量。采用声音搜集装置搜集敲击键盘产生的声音信号&#xff0c;并对声音信号进行巴特沃斯滤波方法进行滤波预处理&#xff1b;将上述经过滤波得到的信号减去环境背景信号&#xff0c;得到当…

http:(5):http状态码

HTTP状态码 当浏览者访问一个网页时&#xff0c;浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前&#xff0c;此网页所在的服务器会返回一个包含HTTP状态码的信息头&#xff08;server header&#xff09;用以响应浏览器的请求。 HTTP状态码的英文为HTT…

[爬虫][python][入门][网页源码][百度图片][豆瓣TOP250]

Robots协议 查看爬取规则 遵守相关法律法规 Robots协议&#xff08;也称为爬虫协议、机器人协议等&#xff09;的全称是“网络爬虫排除标准”&#xff08;Robots Exclusion Protocol&#xff09;&#xff0c;网站通过Robots协议告诉爬虫哪些页面可以抓取&#xff0c;哪些页面不…

mysql(1):查找语句练习

1创建一个员工表 CREATE TABLE employees ( emp_no int(11) NOT NULL, birth_date date NOT NULL, first_name varchar(14) NOT NULL, last_name varchar(16) NOT NULL, gender char(1) NOT NULL, hire_date date NOT NULL, PRIMARY KEY (emp_no)); 2插入数据 insert into em…

[Leedcode][JAVA][面试题 08.11][硬币][动态规划]

【问题描述】 面试题 08.11.硬币 硬币。给定数量不限的硬币&#xff0c;币值为25分、10分、5分和1分&#xff0c;编写代码计算n分有几种表示法。(结果可能会很大&#xff0c;你需要将结果模上1000000007)示例1:输入: n 5输出&#xff1a;2解释: 有两种方式可以凑成总金额: 55…

Java课程设计

目录 Magic-Towers一、团队课程设计博客链接团队博客地址二、个人负责模块或任务说明三、自己的代码提交记录截图四、课程设计感想Magic-Towers 一、团队课程设计博客链接 团队博客地址 二、个人负责模块或任务说明 任务分配  网络1713柳聪灵【组长】--Model游戏布局及障碍物的…

玩转oracle 11g(44):数据库发展历史

数据库发展历史 数据库技术从 20 世纪 60 年代开始到现在一共经历了三个发展阶段&#xff1a;  第一代是网状、层次数据库系统 网状 &#xff1a;通用电气公司 Bachman 等人在 1961 年开发成功的 IDS 层次 &#xff1a; IBM 公司在 1968 年开发的 IMS 第二代是关…

[Java学习资料] [成长之路]

[背景] 网上学习资料千千万万&#xff0c;成长之路千千万万&#xff0c;各取所需 JAVA基础 网站 https://www.runoob.com/java/java-tutorial.html https://www.w3cschool.cn/java/dict 公众号 书籍 算法 网站 labuladong https://github.com/labuladong/fucking-algo…

word 2013 题注、图注、插入图片自动修改大小、批量更新题注编号

1 、题注 图片下面的文字说明&#xff0c;如 图 1.1.1 2、图注 图的标题格式&#xff0c;可以右键修改段落为居中&#xff0c;选中图片&#xff0c;点下此格式快捷居中等其他格式 3、 题注插入 效果 如下 4、题注自动居中对齐 先点击图片--》居中&#xff0c;或者点图注居中…

玩转oracle 11g(45):关系数据库

关系数据库 关系模型 定义&#xff1a;以二维表的形式表示实体和实体之间联系的数据模型称为关系数据模型。 从模型的三要素角度看&#xff0c;关系模型的内容为&#xff1a; &#xff08; 1 &#xff09;数据结构&#xff1a;一张二维表格。 &#xf…

[剑指offer][JAVA]面试题[51][数组中的逆序对][归并排序]

【问题描述】面试题51.数组中的逆序对 &#xff08;困难&#xff09; 在数组中的两个数字&#xff0c;如果前面一个数字大于后面的数字&#xff0c;则这两个数字组成一个逆序对。输入一个数组&#xff0c;求出这个数组中的逆序对的总数。 示例 1:输入: [7,5,6,4] 输出: 5限制&…

2019年1月16日【第三天学习】

2019年1月16日星期三 任务一、运行CrackMe1.exe&#xff0c;提示 "嗯&#xff0c;对了" 代表成功。首先修改exe使得出现成功提示&#xff0c;其次不修改exe输入正确的密码达到成功的目的。 hint:https://blog.csdn.net/Nagi_Way/article/details/68961121 使用.Net的…

玩转oracle 11g(46):图解oracle数据库

1构成 由实例和数据库构成 2构成 3市例 4构成

[Leedcode][JAVA][第46题][全排列][回溯算法]

【问题描述】 46.全排列 &#xff08;中等&#xff09; 给定一个 没有重复 数字的序列&#xff0c;返回其所有可能的全排列。示例:输入: [1,2,3] 输出: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1] ]【解答思路】 1. 回溯 时间复杂度&#xff1a;O(NN&#xff01;) 空间…

java学习(167):生产者消费者问题

class Ck {private char[] r1 new char[8];private int wp 0;public synchronized void shengchan(char aa) {while (wp r1.length) //满了try {this.wait();} catch (Exception e) {}this.notify();//叫醒另一个线程&#xff0c;当前线程处于就绪状态r1[wp] aa;wp;System.…