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
岛屿数量计算算法(不修改原数组)
为了在不修改原数组的情况下计算岛屿的数量,我们可以使用一个辅助数组来标记访问过的陆地单元格。这个辅助数组的大小与原数组相同,并将所有值初始化为false,表示所有单元格都未被访问。在深度优先搜索过程中,我们将访问过的陆地单元格在辅助数组中对应的位置标记为true。
下面是不修改原数组计算岛屿数量的算法实现:
function numIslands(grid) {
if (!grid || grid.length === 0 || grid[0].length === 0) {
return 0;
}
let numIslands = 0;
let rows = grid.length;
let cols = grid[0].length;
let visited = Array.from({length: rows}, () => Array(cols).fill(false));
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (grid[r][c] === '1' && !visited[r][c]) {
dfs(grid, r, c, visited);
numIslands++;
}
}
}
return numIslands;
}
function dfs(grid, r, c, visited) {
const rows = grid.length;
const cols = grid[0].length;
if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] === '0' || visited[r][c]) {
return;
}
visited[r][c] = true; // Mark as visited
// Explore the neighbors in the four directions
dfs(grid, r - 1, c, visited); // up
dfs(grid, r + 1, c, visited); // down
dfs(grid, r, c - 1, visited); // left
dfs(grid, r, c + 1, visited); // right
}
// 示例 1
const grid1 = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
];
console.log(numIslands(grid1)); // 输出:1
// 示例 2
const grid2 = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
];
console.log(numIslands(grid2)); // 输出:3
在上述代码中,我们引入了一个名为visited的二维数组,用于跟踪已经访问过的单元格。在dfs函数中,我们不仅要检查当前单元格是否是陆地,还要检查它是否已经被访问过。如果满足这两个条件,我们才会继续递归地搜索相邻的单元格。这样,我们可以在不修改原数组的情况下计算出岛屿的数量。
为了计算岛屿的最大面积,我们可以在前面的基础上做一些修改。我们仍然使用一个辅助数组来标记访问过的单元格,但是在深度优先搜索过程中,我们会累加每个岛屿的面积,并更新最大面积。
下面是计算岛屿最大面积的算法实现:
function maxAreaOfIsland(gridTemp) {
if (!gridTemp || gridTemp.length === 0 || gridTemp[0].length === 0) {
return 0;
}
let grid = gridTemp.map(x => {
const arr = x.map(y => {
return y.toString()
})
return arr
})
let maxArea = 0;
let rows = grid.length;
let cols = grid[0].length;
let visited = Array.from({length: rows}, () => Array(cols).fill(false));
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
if (grid[r][c] === '1' && !visited[r][c]) {
let area = dfs(grid, r, c, visited);
maxArea = Math.max(maxArea, area);
}
}
}
return maxArea;
}
function dfs(grid, r, c, visited) {
const rows = grid.length;
const cols = grid[0].length;
if (r < 0 || c < 0 || r >= rows || c >= cols || grid[r][c] === '0' || visited[r][c]) {
return 0;
}
visited[r][c] = true; // Mark as visited
let area = 1; // Current cell area
// Explore the neighbors in the four directions and accumulate the area
area += dfs(grid, r - 1, c, visited); // up
area += dfs(grid, r + 1, c, visited); // down
area += dfs(grid, r, c - 1, visited); // left
area += dfs(grid, r, c + 1, visited); // right
return area;
}