Leetcode 200. 岛屿的个数(扩展)
1.题目描述
给定一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000 输出: 1
示例 2:
输入:
11000
11000
00100
00011 输出: 3
2.解题思路
算法核心框架:深度搜索+递归
- 深度搜索:整个岛屿是一个“二维矩阵”(vector<vectro<char>>),使用深度优先搜索遍历一遍整个矩阵;
- 递归:当扫描到'1'时,调用infect()函数,将该 ‘1’ 上下左右相邻的位置都感染为 ‘2’,递归调用infect()的结果是从起始的 ‘1’ 开始而相连的一片‘1’都被感染为 ‘2’;
3.提交代码
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
//行空 或 列空
if(grid.empty() || grid[].empty()){
return ;
}
int N = grid.size();//grid网格的列长
int M = grid[].size();//grid网格的行长
int res = ;
//深度优先搜索
for(int i = ; i < N; ++i){
for(int j = ; j < M; ++j){
if(grid[i][j] == ''){
++res;//只计数作为起始感染点的1的个数,即为岛屿个数
infect(grid,i,j,N,M);
}
}
}
return res;
} void infect(vector<vector<char>>& grid,int i,int j,int N,int M){
if(i< || i>=N || j< || j>= M || grid[i][j] != ''){
return;
}
grid[i][j] = '';
infect(grid,i+,j,N,M);
infect(grid,i-,j,N,M);
infect(grid,i,j-,N,M);
infect(grid,i,j+,N,M);
} };
4.补充知识——并查集
并查集的结构本质是多叉树,是树的一种应用。对于并查集的具体结构,不同的教材版本有不同的定义,我这里介绍的文末所列参考资料中定义。
- 初始时,每个单一元素是一个集合,并且各自的父指针指向自己,各个集合的“代表结点”是其自身;
- 合并时,总是将相对较小的集合合并到大集合中,合并操作只需要将小集合的代表结点的父指针指向大集合的代表结点;
- 查找时,两个元素的代表结点相同,表示在同一个集合。
初始时:每个元素的父指针指向自己
1->1 2->2 3->3 4->4 5->5 合并1,2,得到set1: 2的父指针指向1
2——>1->1 合并3,4,5,得到set2: 集合相等,可以任意选择哪个集合合并到哪个集合,这里3和4并入5
3——>5->5
4——>5->5 合并set1和set2:小集合set1的代表结点的父指针指向set2的代表结点
2——>1——>5->5
3——>5->5
4——>5->5 查找元素2和4是否在同一个集合:
2往上查找得到代表结点为5,4往上查找得到代表结点为5,所以,2和4在同一个集合中。
并查集是一种简单的集合表示,主要的作用有两个:
- 快速的,检查两个元素是否属于同一个集合,isSameSet(A,B);
- 快速的,将两个元素各自所在的不同集合合并在一起,Union(A,B),指的合并A所在的集合set1和B所在的集合set2;
另外,特别注意一点:并查集要求一次性获得所有的处理数据样本,不支持处理动态的数据流。
5.扩展解法——多任务并行计算
假设题目给的数据非常多,也就是所要查找的矩阵相当大,这种情况下,我们该怎么办?很明显,上面的解法只能在单机上运行,效率有上限。
因此,我们需要采用多任务处理的“并行计算”的思路(让你在面试官面前脱颖而出),将大的原始矩阵分割成多个小的矩阵,分布在多台机器上进行计算,最后合并每台机器的岛屿数量,并去重,得到最终的岛屿总数。
#问题的难点:边界信息该如何合并?
01111 | 11110
11000 | 00000
11000 | 00000
01111 | 11110
岛数1 岛数2
合并结果:岛数1 (怎么得到?)
#解决思路:需要保存的关键信息有两个:
- (1)每个分矩阵的岛屿个数;
- (2)记录边界点的感染中心——需要使用到并查集的结构,快速查找两个‘1’是否属于同一个集合(相同的感染中心)。
举例:划分为2个矩阵
矩阵1 矩阵2
|
|
|
|
|
()矩阵1的岛屿个数为2,矩阵2的岛屿个数为2
()边界点的感染中心:为了易于区别不同的'',设红、蓝、黑、绿色岛屿的感染中心(感染起始点的那个'')的分别为A、B、C、D
0A111 | B1110
0 | 0000
|000D
0C111 | 000
0000 | 00
第1行边界的两个1,感染中心分别为A和B,不相同,岛屿数减一,并且将感染中心为B的岛屿上的1的感染中心全部置为A;
第2行边界的两个1,感染中心分别为A和A(岛屿B的感染中心在上一步更新为A了),相同,跳过;
第3行边界的两个不全为1,跳过;
第4行边界的两个1,感染中心分别为C和A,不相同,岛屿数减一,并且将感染中心为C的岛屿上的1的感染中心全部置为A;
第5行边界的两个不全为1,跳过; 岛屿总数:2+2 -1 -1 = 2
两个分矩阵的合并处理解决了,四个或八个矩阵的合并同理,只是需要重复的步骤多了。
参考资料:
1.《数据结构考研复习指导》--王道单科书 www.cskaoyan.com
2.《算法初级班视频 》--牛客网大牛 · 左程云
Leetcode 200. 岛屿的个数(扩展)的更多相关文章
- LeetCode 200. 岛屿的个数(Number of Islands)
题目描述 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1 ...
- LeetCode 200.岛屿的个数
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入: ...
- leetcode 200岛屿的个数
主要考察图搜索: 方法一:染色法,时间O(mn) 遍历一遍,再通过BFS或DFS将所有临近岛屿染色,使用dfs时将numIslands中的bfs换成dfs即可: /***** 遍历所有的点: 只要遇见 ...
- Leetcode 200.岛屿的数量 - DFS、BFS
Leetcode 200 岛屿的数量: DFS利用函数调用栈保证了检索顺序, BFS则需要自己建立队列,把待检索对象按规则入队. class Solution { // DFS解法,8ms/10.7M ...
- Java实现 LeetCode 200 岛屿数量
200. 岛屿数量 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. ...
- 【LeetCode】200. 岛屿的个数
题目 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1:输 ...
- LeetCode 200. 岛屿数量
习题地址 https://leetcode-cn.com/problems/number-of-islands/ 给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水 ...
- 力扣Leetcode 200. 岛屿数量
岛屿数量 给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量. 岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成. 此外,你可以假设该网 ...
- [LeetCode] Number of Distinct Islands II 不同岛屿的个数之二
Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) conn ...
随机推荐
- PHP计算两个已知经纬度之间的距离
/** *求两个已知经纬度之间的距离,单位为千米 *@param lng1,lng2 经度 *@param lat1,lat2 纬度 *@return float 距离,单位千米 **/ privat ...
- HADOOP docker(六):hive简易使用指南
前言1.hive简介1.1 hive组件与相应功能:1.2 hive的表类型1.3 分区表1.3 分隔符1.4 hive的数据存储2.数据类型2.1 基本数据类型2.1 复杂数据类型2.3 NULL3 ...
- 阿里云搭建bind服务,外网ip不能用来解析问题解决
options { listen-on port 53 { any; }; //端口开放any listen-on-v6 port 53 { ::1; }; directory "/var/ ...
- js实现滑动器效果
最近公司在做一个项目,页面中要用到滑动器效果,我的第一反应是使用HTML5 input类型中的range类型,但马上我就否定了这个想法,因为range类型存在浏览器的兼容性问题(在主流浏览器中).但又 ...
- 关于智能指针类型shared_ptr的计数问题
一.关键 每个shared_ptr所指向的对象都有一个引用计数,它记录了有多少个shared_ptr指向自己 shared_ptr的析构函数:递减它所指向的对象的引用计数,如果引用计数变为0,就会销毁 ...
- 重构 之 总结代码的坏味道 Bad Smell (一) 重复代码 过长函数 过大的类 过长参数列 发散式变化 霰弹式修改
膜拜下 Martin Fowler 大神 , 开始学习 圣经 重构-改善既有代码设计 . 代码的坏味道就意味着需要重构, 对代码的坏味道了然于心是重构的比要前提; . 作者 : 万境绝尘 转载请注明出 ...
- 软工时间-Alpha 冲刺 (2/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 学习了UI设计软件的使用,了解了项目开发的具体流程. 展示 ...
- 总结Canvas和SVG的区别
参考链接: 菜鸟教程 HTML5 内联SVG 经典面试题(讨论canvas与svg的区别) Canvas SVG 通过 JavaScript 来绘制 2D 图形 是一种使用 XML 描述 2D 图形的 ...
- iOS- <项目笔记>iOS6 & iOS7屏幕图片适配
1.为非视网膜\视网膜屏幕分别准备2份图片,比如: 1> 非视网膜 abc.png 2> 视网膜 abc@2x.png 程序检测视网膜屏到会自动替换@2x 2.程序启动图片 * 程序启动过 ...
- BAT批处理(六)
字符串处理 批处理有着具有非常强大的字符串处理能力,其功能绝不低于C语言里面的字符串函数集.批处理中可实现的字符串处理功能有:截取字符串内容.替换字符串特定字段.合并字符串.扩充字符串等功能.下面对这 ...