编码母题 / P1 / 经典算法 / 08
岛屿数量与最大岛屿面积
重要程度必练难度中等预计完成30–40 分钟
题目是什么
输入只含数字 0 和 1 的矩形二维数组 grid;上下左右相邻的 1 连成一座岛,对角相邻不连通。返回 { count, maxArea },面积为岛内 1 的个数;空网格返回两个 0,且不得修改输入。
输入输出示例
[[1,1,0],[0,1,0],[1,0,1]] 含 3 座岛,最大岛面积 3,返回 { count: 3, maxArea: 3 }。
练习起手式与验证
/*
* 题目:岛屿数量与最大岛屿面积
* 要求:输入只含数字 0 和 1 的矩形二维数组 grid;上下左右相邻的 1 连成一座岛,对角相邻不连通。返回 { count, maxArea },面积为岛内 1 的个数;空网格返回两个 0,且不得修改输入。
* 示例:[[1,1,0],[0,1,0],[1,0,1]] 含 3 座岛,最大岛面积 3,返回 { count: 3, maxArea: 3 }。
*/
function analyzeIslands(grid) {}
console.log(analyzeIslands([[1, 1, 0], [0, 1, 0], [1, 0, 1]])); // 预期:{ count: 3, maxArea: 3 }
console.log(analyzeIslands([])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[0, 0], [0, 0]])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[1, 1], [1, 1]])); // 预期:{ count: 1, maxArea: 4 }
/*
* 题目:岛屿数量与最大岛屿面积
* 要求:输入只含数字 0 和 1 的矩形二维数组 grid;上下左右相邻的 1 连成一座岛,对角相邻不连通。返回 { count, maxArea },面积为岛内 1 的个数;空网格返回两个 0,且不得修改输入。
* 示例:[[1,1,0],[0,1,0],[1,0,1]] 含 3 座岛,最大岛面积 3,返回 { count: 3, maxArea: 3 }。
*/
function analyzeIslands(grid) {}
console.log(analyzeIslands([[1, 1, 0], [0, 1, 0], [1, 0, 1]])); // 预期:{ count: 3, maxArea: 3 }
console.log(analyzeIslands([])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[0, 0], [0, 0]])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[1, 1], [1, 1]])); // 预期:{ count: 1, maxArea: 4 }解题思路与实现
展开解题思路
每遇到未访问陆地就启动一次迭代搜索;一次搜索恰好覆盖一个连通分量。
function analyzeIslands(grid) {
if (!Array.isArray(grid) || !grid.length) return { count: 0, maxArea: 0 };
const columns = grid[0].length;
if (!grid.every((row) => Array.isArray(row) && row.length === columns))
throw new TypeError("grid must be rectangular");
const visited = Array.from({ length: grid.length }, () =>
Array(columns).fill(false),
);
const directions = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
let count = 0;
let maxArea = 0;
for (let r = 0; r < grid.length; r += 1)
for (let c = 0; c < columns; c += 1) {
if (!grid[r][c] || visited[r][c]) continue;
count += 1;
let area = 0;
const stack = [[r, c]];
visited[r][c] = true;
while (stack.length) {
const [row, column] = stack.pop();
area += 1;
for (const [dr, dc] of directions) {
const nr = row + dr;
const nc = column + dc;
if (
nr >= 0 &&
nr < grid.length &&
nc >= 0 &&
nc < columns &&
grid[nr][nc] &&
!visited[nr][nc]
) {
visited[nr][nc] = true;
stack.push([nr, nc]);
}
}
}
maxArea = Math.max(maxArea, area);
}
return { count, maxArea };
}
// 三组以上可直接运行的验证。
console.log(analyzeIslands([[1, 1, 0], [0, 1, 0], [1, 0, 1]])); // 预期:{ count: 3, maxArea: 3 }
console.log(analyzeIslands([])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[0, 0], [0, 0]])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[1, 1], [1, 1]])); // 预期:{ count: 1, maxArea: 4 }
function analyzeIslands(grid) {
if (!Array.isArray(grid) || !grid.length) return { count: 0, maxArea: 0 };
const columns = grid[0].length;
if (!grid.every((row) => Array.isArray(row) && row.length === columns))
throw new TypeError("grid must be rectangular");
const visited = Array.from({ length: grid.length }, () =>
Array(columns).fill(false),
);
const directions = [
[1, 0],
[-1, 0],
[0, 1],
[0, -1],
];
let count = 0;
let maxArea = 0;
for (let r = 0; r < grid.length; r += 1)
for (let c = 0; c < columns; c += 1) {
if (!grid[r][c] || visited[r][c]) continue;
count += 1;
let area = 0;
const stack = [[r, c]];
visited[r][c] = true;
while (stack.length) {
const [row, column] = stack.pop();
area += 1;
for (const [dr, dc] of directions) {
const nr = row + dr;
const nc = column + dc;
if (
nr >= 0 &&
nr < grid.length &&
nc >= 0 &&
nc < columns &&
grid[nr][nc] &&
!visited[nr][nc]
) {
visited[nr][nc] = true;
stack.push([nr, nc]);
}
}
}
maxArea = Math.max(maxArea, area);
}
return { count, maxArea };
}
// 三组以上可直接运行的验证。
console.log(analyzeIslands([[1, 1, 0], [0, 1, 0], [1, 0, 1]])); // 预期:{ count: 3, maxArea: 3 }
console.log(analyzeIslands([])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[0, 0], [0, 0]])); // 预期:{ count: 0, maxArea: 0 }
console.log(analyzeIslands([[1, 1], [1, 1]])); // 预期:{ count: 1, maxArea: 4 }
时间复杂度:O(R·C)。每个网格单元最多入栈和检查有限次。
空间复杂度:O(R·C)。访问标记及最坏情况下的搜索栈覆盖整个网格。