小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
原题:200. 岛屿数量
题目大意:给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
例如:
输入:grid = [ ["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3
解题思路:
首先,我们需要在二维数组中对元素进行遍历,每当便利到一个元素的值是 1,那么就有一个岛屿。此时,与之上下左右相连的值为 1 的元素也属于这个岛屿,并且这个规则是递归的,也就是,「相连的 1」和「相连的 1 的相连的 1」都属于这个岛屿,因此,此处会用到递归。如果把值为 1 的元素的相连关系看作一个图的话,那么就是对这个图进行一次深度优先遍历。对图的深度优先便利的过程中需要标记访问过的元素,在这个题中,我们可以直接把访问过的元素的值修改为 0 ,而不需要在创建一个标记的数组。
当把一个值为 1 的元素的直接和间接相邻的 1 都标记为 0 之后,它所在的岛屿就在原始的数组中消失了,此时就可以接着遍历去寻找下一个岛屿,知道把整个二维数组都遍历完。
最终代码:
class Solution {
public int numIslands(char[][] grid) {
int r = grid.length;
if (r == 0) {
return 0;
}
int c = grid[0].length;
int count = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (grid[i][j] == '1') {
count++;
dfs(grid, i, j);
}
}
}
return count;
}
private void dfs(char[][] grid, int i, int j) {
grid[i][j] = '0';
int[][] moves = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
for (int[] move : moves) {
int x = i + move[0], y = j + move[1];
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length && grid[x][y] == '1') {
dfs(grid, x, y);
}
}
}
}
代码中有几点值得注意的地方:
- 统计岛屿数量的
count++在 dfs 方法的外面,不然会重复统计。 - 在访问各个元素上下左右相邻元素的时候,一定要判断而为数组的边界,如果元素在数组的边界处,那么并不是每一个方向都有相邻的元素,忘记判断会导致程序异常。