岛屿数量
LeetCode 200. 岛屿数量
题目描述
给你一个由 '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,因为一块陆地是 1,十块陆地也是 1,因此遇到陆地就可以先计数+1,然后相邻的陆地全部标记为水,这样就不会重复计数了
- 递归遍历,直到遇到水为止
- 时间复杂度 O(m*n)
- 空间复杂度 O(m*n)
- 递归深度最大为 m*n
- 递归停止条件:越界、遇到水、已经遍历过的陆地
- 深度遍历优先
代码
javascript
var numIslands = function (grid) {
// 岛屿计数
let count = 0;
// 遍历矩阵
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
// 岛屿数量+1
count++;
// 进行沉岛操作
turnZero(grid, i, j);
}
}
}
// 找到岛屿后 把相邻的岛屿全部设置为海 因为是求数量 只留一块即可
// 沉岛 函数
function turnZero(grid, i, j) {
// 如果到了边界 则不需要操作
if (grid[i]?.[j] === undefined) return;
// 已经是海洋 不需要再次操作
if (grid[i][j] == 0) return;
// 对自己和上下左右进行沉岛,也就是变为 0
grid[i][j] = 0;
turnZero(grid, i - 1, j);
turnZero(grid, i, j + 1);
turnZero(grid, i + 1, j);
turnZero(grid, i, j - 1);
}
return count;
};
为什么不会重复计数
因为遍历的时候,遇到陆地后马上进行 DFS 深度遍历优先递归相邻的元素,在下一次遍历前会把陆地全部变为水,这样就不会重复计数了。