文章目录
前言
岛屿类问题,最简单的处理方式就是使用深度优先遍历来解,找到一个陆地后,不断的向其上下左右四个方向进行遍历,直到抵达边界或者水域为止。
我们先从一道LeetCode上的题目了解一下一般岛屿类题目的问题场景。
第一题:求岛屿的周长

题目了解完,我们就先来梳理一下解题思路。
模板整理
首先按照深度优先遍历的思想,肯定是先找到遍历的方式,一般网格类,我们可以按照上下左右四个方向进行遍历,再外加两个参数,r表示行,c表示列。
我们可以写出如下方法。
遍历方向
public 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);
}
假设现在位于坐标(1,1)上,那么其上下左右分别就是(0,1)、(2,1)、(1,0)、(1,2)

接下来,我们就要考虑边界问题,首先就是网格的边界值,其实也就是行和列的边界值。
确定边界
public void dfs(int[][] grid, int r, int c) {
// 网格的边界值
if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) {
return;
}
// 上
dfs(grid, r - 1, c);
// 下
dfs(grid, r + 1, c);
// 左
dfs(grid, r, c - 1);
// 右
dfs(grid, r, c + 1);
}
当处理完边界值之后,我们就要考虑遍历到水域的问题了,很明显,当遍历到水域时,也就可以停止了。
public void dfs(int[][] grid, int r, int c) {
// 网格的边界值
if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) {
return;
}
// 当遍历到水域时,就应当停止了
if (grid[r][c] == 0) {
return;
}
// 上
dfs(grid, r - 1, c);
// 下
dfs(grid, r + 1, c);
// 左
dfs(grid, r, c - 1);
// 右
dfs(grid, r, c + 1);
}
重复遍历问题处理
到此,我们已经确定了深度优先遍历的边界条件,现在我们要考虑一下实际场景的问题,按照我们现在的边界停止条件,忽略了如下的场景:

就是说,坐标(1,1)和(2,1)会互相作用,导致永远搜索不完,所以针对这种情况,我们还需要进行额外的处理,处理方式也很简单,一般情况下我们只需要记录一下每次走过的位置即可,当然方式有很多,比如放到Set集合,岛屿问题可以简单点处理,直接改变原有的值即可,比如直接将1改为2。
那么现在坐标(1,1)的值为2,然后要走到(2,1)。

走到(2,1)后,我们也把值改为2,此时又从坐标(2,1)开始遍历,当向上遍历到(1,1)时就会直接停止了,因为此时(1,1)的值已经被改为2,即表示遍历过了。

到此为止,我们就算完成了一个标准的深度遍历模板了,现在可以用它来解题了!
模板解第一题
我们回到求岛屿的周长的问题,可以发现,所要找的岛屿的边,可以分为两种情况,一种是当遍历到网格边界时,其边界就是一条边,第二种情况就是,当遍历到水域时,也会有一条边。

代码如下
public int islandPerimeter(int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
// 当遇到水域时,开始进行遍历
if (grid[i][j] == 1) {
return dfs(grid, i, j);
}
}
}
return 0;
}
public int dfs(int[][] grid, int r, int c) {
// 走向边界,周长加1
if (r < 0 || r >= grid.length || c < 0 || c >= grid[0].length) {
return 1;
}
// 走向水域,周长加1
if (grid[r][c] == 0) {
return 1;
}
// 遍历过了,周长不变,直接返回
if (grid[r][c] == 2) {
return 0;
}
// 遍历过的陆地,设置为2,以免重复遍历
grid[r][c] = 2;
// 最后累加所有遍历结果
return dfs(grid, r - 1, c)
+ dfs(grid, r + 1, c)
+ dfs(grid, r, c - 1)
+ dfs(grid

文章详细介绍了使用深度优先遍历解决岛屿问题的通用模板,包括遍历方向、边界确定、重复遍历问题处理等,并通过六道题目展示了模板的应用,如求岛屿周长、数量、最大面积、子岛屿统计和封闭岛屿数目等,强调了模板的灵活性和适应性。

292

被折叠的 条评论
为什么被折叠?



