给定一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
示例 1:
输入:
11110
11010
11000
00000
输出: 1
示例 2:
输入:
11000
11000
00100
00011
输出: 3
思路一:深度优先遍历
将二维网格看成一个无向图,然后相邻的1之间有边。通过线性遍历数组,每到一个1便启动深度优先遍历,遍历过的都置为0。每次启动都计数,最终得到的就是岛屿的个数了。
- 时间复杂度 : O(M×N),其中 M 和 N 分别为行数和列数。
- 空间复杂度 : 最坏情况下为 O(M×N),此时整个网格均为陆地,深度优先搜索的深度达到 M×N。
class Solution {
/**
*线性遍历数组,每遇到1启动dfs,启动则计数器加一
*/
public int numIslands(char[][] grid) {
int nr = grid.length;
if(nr==0) return 0;
int nc = grid[0].length;
int res = 0;
for(int r=0;r<nr;r++){
for(int c=0;c<nc;c++){
if(grid[r][c]=='1'){
res++;
dfs(grid,r,c);
}
}
}
return res;
}
/**
*深度优先遍历,r代表行号,c代表列号
*当数组越界或者当前数为0时返回,为1则继续递归深度遍历
*/
public 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);
}
}
思路二:广度优先遍历
原理和思路一是一样的,只是遍历的方式不同。深度优先遍历使用递归,而广度优先遍历不需要递归,使用队列+while。
需要注意的是:广度优先遍历在入队一个节点时便标志着对它的遍历完成,应该在此时将其标志位置0,而不是在出队的时候。
- 时间复杂度 : O(M×N),其中 M 和 N 分别为行数和列数。
- 空间复杂度 : 最坏情况下为 O(min(M,N)),此时整个网格均为陆地,队列的大小可达到 min(M,N)。
class Solution {
/**
*线性遍历数组,每遇到1启动bfs,启动则计数器加一
*/
public int numIslands(char[][] grid) {
int nr = grid.length;
if(nr==0) return 0;
int nc = grid[0].length;
int res = 0;
for(int r=0;r<nr;r++){
for(int c=0;c<nc;c++){
if(grid[r][c]=='1'){
res++;
bfs(grid,r,c);
}
}
}
return res;
}
/**
*使用一个队列来存储当前节点的邻居的下标,通过“行号*列数+列号”的方式标志
*/
public void bfs(char[][] grid,int r,int c){
int nr = grid.length;
int nc = grid[0].length;
Queue<Integer> neighbors = new LinkedList<Integer>();
neighbors.offer(r*nc + c);
while(!neighbors.isEmpty()){
int index = neighbors.poll();
int ri = index/nc;
int ci = index%nc;
if(ri-1>=0 && grid[ri-1][ci]=='1'){
neighbors.offer((ri-1)*nc+ci);
grid[ri-1][ci] = '0';
}
if(ci-1>=0 && grid[ri][ci-1]=='1'){
neighbors.offer((ri)*nc+ci-1);
grid[ri][ci-1] = '0';
}
if(ri+1<nr && grid[ri+1][ci]=='1'){
neighbors.offer((ri+1)*nc+ci);
grid[ri+1][ci] = '0';
}
if(ci+1<nc && grid[ri][ci+1]=='1'){
neighbors.offer((ri)*nc+ci+1);
grid[ri][ci+1] = '0';
}
}
}
}
思路三:并查集
暂时不懂,以后再说。