我是借鉴nettee大佬写的题解完成的此篇博客,他使用循序渐进的方法来完成
nettee大佬的题解链接
这道题属于一类经典的方格搜索题目。有 m×n 个小方格,组成一个网格,每个小方格与其上下左右四个方格认为是相邻的,要在这样的网格上进行某种搜索。这种题目乍一看可能有点麻烦,实际上非常简单,尤其是用 DFS 的方法。题目没有限制的话,我们尽量用 DFS 来写代码。
下面我们一步步地构造出方格类 DFS 的代码。
首先,每个方格与其上下左右的四个方格相邻,则 DFS 每次要分出四个岔:
// 基本的 DFS 框架:每次搜索四个相邻方格
void dfs(int[][] grid, int r, int c) {
dfs(grid, r - 1, c); // 上边相邻
dfs(grid, r + 1, c); // 下边相邻
dfs(grid, r, c - 1); // 左边相邻
dfs(grid, r, c + 1); // 右边相邻
}
但是,对于网格边缘的方格,上下左右并不都有邻居。一种做法是在递归调用之前判断方格的位置,例如位于左边缘,则不访问其左邻居。但这样一个一个判断写起来比较麻烦,我们可以用“先污染后治理”的方法,先做递归调用,再在每个 DFS 函数的开头判断坐标是否合法,不合法的直接返回。同样地,我们还需要判断该方格是否有岛屿(值是否为 1),否则也需要返回。
// 处理方格位于网格边缘的情况
void dfs(int[][] grid, int r, int c) {
// 若坐标不合法,直接返回
if (!(0 <= r && r < grid.length && 0 <= c && c < grid[0].length)) {
return;
}
// 若该方格不是岛屿,直接返回
if (grid[r][c] != 1) {
return;
}
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
但是这样还有一个问题,停不下来。
那么我们需要标记遍历过的方格,保证方格不进行重复遍历。标记遍历过的方格并不需要使用额外的空间,只需要改变方格中存储的值就可以。在这道题中,值为 0 表示非岛屿(不可遍历),值为 1 表示岛屿(可遍历),我们用 2 表示已遍历过的岛屿。遍历代码修改如下:
// 标记已遍历过的岛屿,不做重复遍历
void dfs(int[][] grid, int r, int c) {
if (!(0 <= r && r < grid.length && 0 <= c && c < grid[0].length)) {
return;
}
// 已遍历过(值为2)的岛屿在这里会直接返回,不会重复遍历
if (grid[r][c] != 1) {
return;
}
grid[r][c] = 2; // 将方格标记为"已遍历"
dfs(grid, r - 1, c);
dfs(grid, r + 1, c);
dfs(grid, r, c - 1);
dfs(grid, r, c + 1);
}
package LeetCode.FiveHundredOneToOneThousand;
public class SixHundredAndNinetyFive {
public int maxAreaOfIsland(int[][] grid) {
//首先判断是否为零
if (grid.length == 0 || grid[0].length == 0) return 0;
//然后将其挨个计算
int max = 0;
for (int r = 0; r < grid.length; r++){
for (int c = 0; c < grid[0].length; c++){
if (grid[r][c] == 1){
int temp = dfs(grid, r, c);
max = Math.max(temp, max);
}
}
}
return max;
}
private int dfs(int [][] grid, int r, int c){
//判断数据是否合法
if (!(r >= 0 && r < grid.length && c >= 0 && c < grid[0].length)) return 0;
//判断当前值是否为1
if (grid[r][c] != 1) return 0;
//将计算过的岛屿记为0
grid[r][c] = 0;
//递归计算最大的岛屿数
return 1+
dfs(grid, r + 1, c) +
dfs(grid, r - 1, c) +
dfs(grid, r, c + 1) +
dfs(grid, r, c - 1);
}
}