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[0].empty()){ return 0; } int N = grid.size();//grid网格的列长 int M = grid[0].size();//grid网格的行长 int res = 0; //深度优先搜索 for(int i = 0; i < N; ++i){ for(int j = 0; j < M; ++j){ if(grid[i][j] == '1'){ ++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<0 || i>=N || j<0 || j>= M || grid[i][j] != '1'){ return; } grid[i][j] = '2'; infect(grid,i+1,j,N,M); infect(grid,i-1,j,N,M); infect(grid,i,j-1,N,M); infect(grid,i,j+1,N,M); } };
4.扩展解法——并查集
假设题目给的数据非常多,也就是所要查找的矩阵相当大,这种情况下,我们该怎么办?很明显,上面的解法只能在单机上运行,效率有上限。
因此,我们需要采用多任务处理的“并行计算”的思路,将大的原始矩阵分割成多个小的矩阵,分布在多台机器上进行计算,最后合并每台机器的岛屿数量,并去重,得到最终的岛屿总数。
#问题的难点:边界信息该如何合并?
01111 | 11110 11000 | 00000 11000 | 00000 01111 | 11110 岛数1 岛数2 合并结果:岛数1 (怎么得到?)
#解决思路:需要保存的关键信息有两个:
- (1)每个分矩阵的岛屿个数;
- (2)记录边界点的感染中心——需要使用到并查集的结构,快速查找两个‘1’是否属于同一个集合(相同的感染中心)。
#并查集知识点