最大人工岛
难度:
标签:
题目描述
代码结果
运行时间: 413 ms, 内存: 27.6 MB
/*
* 思路:
* 1. 使用流的方式遍历矩阵中的每一个0,尝试将其变为1并计算岛屿面积。
* 2. 使用递归计算岛屿面积。
* 3. 使用流收集最大面积。
*/
import java.util.Arrays;
public class Solution {
private int n;
private int[][] grid;
private final int[] dX = {-1, 1, 0, 0};
private final int[] dY = {0, 0, -1, 1};
public int largestIsland(int[][] grid) {
this.n = grid.length;
this.grid = grid;
return Arrays.stream(grid)
.flatMapToInt(row -> Arrays.stream(row))
.filter(cell -> cell == 0)
.map(cell -> {
grid[cell / n][cell % n] = 1;
int area = Arrays.stream(grid)
.mapToInt(row -> Arrays.stream(row)
.map(this::calculateArea)
.max()
.orElse(0))
.max()
.orElse(0);
grid[cell / n][cell % n] = 0;
return area;
})
.max()
.orElse(0);
}
private int calculateArea(int cell) {
return Arrays.stream(new int[]{-1, 1, 0, 0})
.flatMap(dx -> Arrays.stream(new int[]{0, 0, -1, 1})
.map(dy -> dfs(cell / n + dx, cell % n + dy, new boolean[n][n])))
.sum() + 1;
}
private int dfs(int x, int y, boolean[][] visited) {
if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] == 0 || visited[x][y]) {
return 0;
}
visited[x][y] = true;
return 1 + Arrays.stream(new int[]{-1, 1, 0, 0})
.flatMap(dx -> Arrays.stream(new int[]{0, 0, -1, 1})
.map(dy -> dfs(x + dx, y + dy, visited)))
.sum();
}
}
解释
方法:
这个题解采用了深度优先搜索(DFS)的思路。首先,遍历整个网格,对于每个值为1的格子,执行DFS遍历其连通的1,并标记为一个新的岛屿编号(dum),同时记录该岛屿的面积。接着,再次遍历网格,对于每个值为0的格子,计算若将其变为1后,能够连接到的岛屿的面积之和,更新最大面积。最后返回最大面积。
时间复杂度:
O(n^2)
空间复杂度:
O(n^2)
代码细节讲解
🦆
在执行DFS时,为何选择将已访问的'1'改为岛屿编号'dum'而不是其他标记方式?这种方式在处理复杂网格时有什么优势?
▷🦆
题解中提到对于每个'0'格子,通过计算与其相邻的岛屿面积来更新最大面积。请问如果一个'0'格子相邻四个方向都是不同的岛屿,算法是如何避免重复计算相邻岛屿面积的?
▷🦆
题解中在所有岛屿标记完成后检查了'dum==1'和'dtom[2]==li*lj'的情况,这两个检查分别处理了什么特殊情况?
▷🦆
如果n非常大接近500,递归的DFS方法可能会引起栈溢出。题解是否考虑了这个问题?如果没有,有什么其他方法可以避免这种情况?
▷