岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
示例 2:
输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j] 的值为 ‘0’ 或 ‘1’
- 遍历数组的每一个元素,如果遇到岛屿,岛屿数量加1,并将这一整块岛屿都标记下,表示已经计数过了,避免重复计数
- 将整块岛屿都标记的方法是遍历整个岛屿,将每个元素都标记。可以采用BFS或DFS。
BFS
//BFS
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length; //row 行数
int nc = grid[0].length; //colnmn 列数
int islandNumber = 0; //统计岛屿数量
for( int r = 0 ; r < nr ; ++r){
for( int c = 0 ; c < nc ; ++c){ //双层循环,确保每个元素被遍历
if(grid[r][c] == '1'){ //如果摸到了岛屿,岛屿数量加一,通过BFS遍历整个岛屿并且标记。表示该岛屿已经被计数过。避免重复计数
ArrayDeque<Integer> neighbors = new ArrayDeque<>();
neighbors.add( r * nc + c ); //用id保存元素的行标和列标
grid[r][c] = '2'; //访问过的岛屿就置为二,方便区分是否访问过,如果置为0就和水区分不开了,入队时就置为2,如果出队时才置为2,一个元素可能重复入队
++islandNumber;
while (!neighbors.isEmpty()){ //当队列不为空,通过BFS遍历整个岛屿并且标记,队列为空了,说明整块岛屿遍历完了
int id = neighbors.remove();
int row = id / nc;
int colnmn = id % nc;
//将正在处理的岛屿四周的未访问过岛屿也加进队列
if(row-1 >=0 && grid[row-1][colnmn] == '1'){ //判断上方元素是否应入队
neighbors.add(colnmn + nc * (row-1) );
grid[row-1][colnmn] = '2'; //如果出队时才置为2,一个元素可能重复入队
}
if(row+1 < nr && grid[row+1][colnmn] == '1'){ //判断下方元素是否应入队
neighbors.add(colnmn + nc * (row+1) );
grid[row+1][colnmn] = '2'; //如果出队时才置为2,一个元素可能重复入队
}
if(colnmn-1 >=0 && grid[row][colnmn-1] == '1'){ //判断左方元素是否应入队
neighbors.add(colnmn-1 + row * nc );
grid[row][colnmn-1] = '2'; //如果出队时才置为2,一个元素可能重复入队
}
if(colnmn+1 < nc && grid[row][colnmn+1] == '1'){ //判断右方元素是否应入队
neighbors.add(colnmn+1 + row * nc );
grid[row][colnmn+1] = '2'; //如果出队时才置为2,一个元素可能重复入队
}
}//while (!neighbors.isEmpty())
}// if(grid[r][c] == '1')
}
}//双层for
return islandNumber;
}
DFS
public class NumberOfIslandsSta {
public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
int nr = grid.length; //row 行数
int nc = grid[0].length; //colnmn 列数
int islandNumber = 0; //统计岛屿数量
for( int r = 0 ; r < nr ; ++r){
for( int c = 0 ; c < nc ; ++c){ //双层循环,确保每个元素被遍历
if(grid[r][c] == '1'){ //如果摸到了岛屿,岛屿数量加一,通过BFS遍历整个岛屿并且标记。表示该岛屿已经被计数过。避免重复计数
Dfs(grid,r,c);
++islandNumber;
}// if(grid[r][c] == '1')
}
}//双层for
return islandNumber;
}
private void Dfs(char[][] grid, int i , int j){
if( i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] == '0')
return;
grid[i][j] = '0';
Dfs(grid,i-1, j);
Dfs(grid,i+1, j);
Dfs(grid,i,j-1);
Dfs(grid,i,j+1);
}
}