LeetCode 上的岛屿问题通常是关于矩阵中岛屿的数量、面积、周长等问题。这些问题可以归纳为图的遍历问题,常见的解决方法包括深度优先搜索(DFS)和广度优先搜索(BFS)。 今天汇总一下我做过的一些DFS解决的岛屿问题。
463. 岛屿的周长 - 力扣(LeetCode)
给定一个 row x col
的二维网格地图 grid
,其中:grid[i][j] = 1
表示陆地, grid[i][j] = 0
表示水域。
网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。
岛屿中没有"湖"("湖" 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
示例 1:
css
输入: grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
输出: 16
解释: 它的周长是上面图片中的 16 个黄色的边
示例 2:
lua
输入: grid = [[1]]
输出: 4
示例 3:
lua
输入: grid = [[1,0]]
输出: 4
提示:
row == grid.length
col == grid[i].length
1 <= row, col <= 100
grid[i][j]
为0
或1
代码
py
class Solution:
def islandPerimeter(self, grid):
def dfs(grid, i, j):
if not 0 <= i < len(grid) or not 0 <= j < len(grid[0]) or grid[i][j] == 0:
return 1
if grid[i][j] == -1:
return 0
grid[i][j] = -1
t = dfs(grid, i - 1, j)
b = dfs(grid, i + 1, j)
l = dfs(grid, i, j - 1)
r = dfs(grid, i, j + 1)
return t + b + l + r
count = 0
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
count += dfs(grid, i, j)
return count
这个问题的解法是使用深度优先搜索(DFS)。
-
dfs
函数是递归地计算从当前位置(i, j)
出发的岛屿的周长。- 如果当前位置越界或者是水域(
grid[i][j] == 0
),返回 1(表示边界)。 - 如果当前位置已经被访问过(
grid[i][j] == -1
),返回 0。 - 将当前位置标记为已访问(
grid[i][j] = -1
)。 - 递归地计算当前位置的上、下、左、右四个方向的周长,并将结果相加。
- 如果当前位置越界或者是水域(
-
主函数
islandPerimeter
遍历整个网格,当发现岛屿(grid[i][j] == 1
)时,调用dfs
函数计算该岛屿的周长,并累加到count
变量中。 -
最终返回累加的周长
count
。
这样,通过深度优先搜索递归计算每个岛屿的周长,最终得到整个岛屿的总周长。这题的关键点是在计算周长时,遇到岛屿的边界要返回1,同时需要标记已经访问过的岛屿,避免重复计算。
695. 岛屿的最大面积 - 力扣(LeetCode)
给你一个大小为 m x n
的二进制矩阵 grid
。
岛屿 是由一些相邻的 1
(代表土地) 构成的组合,这里的「相邻」要求两个 1
必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid
的四个边缘都被 0
(代表水)包围着。
岛屿的面积是岛上值为 1
的单元格的数目。
计算并返回 grid
中最大的岛屿面积。如果没有岛屿,则返回面积为 0
。
示例 1:
css
输入: grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]]
输出: 6
解释: 答案不应该是 11 ,因为岛屿只能包含水平或垂直这四个方向上的 1 。
示例 2:
lua
输入: grid = [[0,0,0,0,0,0,0,0]]
输出: 0
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 50
grid[i][j]
为0
或1
代码
py
class Solution:
def maxAreaOfIsland(self, grid):
m, n = len(grid), len(grid[0])
def dfs(grid, i, j):
if not 0 <= i < m or not 0 <= j < n or grid[i][j] == 0:
return 0
grid[i][j] = 0
t = dfs(grid, i - 1, j)
b = dfs(grid, i + 1, j)
l = dfs(grid, i, j - 1)
r = dfs(grid, i, j + 1)
return t + b + l + r + 1
maxS = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
s = dfs(grid, i, j)
maxS = max(maxS,s)
return maxS
这个解法同样是使用深度优先搜索(DFS)。以下是对代码的解析:
-
dfs
函数负责计算从当前位置(i, j)
出发的岛屿的面积。- 如果当前位置越界或者是水域(
grid[i][j] == 0
),返回 0。 - 将当前位置标记为已访问(
grid[i][j] = 0
)。 - 递归地计算当前位置的上、下、左、右四个方向的面积,并将结果相加。
- 最终返回当前位置的面积 + 1,表示当前位置是陆地。
- 如果当前位置越界或者是水域(
-
主函数
maxAreaOfIsland
遍历整个网格,当发现岛屿(grid[i][j] == 1
)时,调用dfs
函数计算该岛屿的面积,并与当前最大面积maxS
比较,更新maxS
。 -
最终返回最大面积
maxS
。
这个解法的核心思想是通过深度优先搜索递归地计算每个岛屿的面积,并在遍历过程中不断更新最大面积。同样地,已经访问过的陆地需要标记为水域,以避免重复计算。
200. 岛屿数量 - 力扣(LeetCode)
给你一个由 '1'
(陆地)和 '0'
(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
css
输入: grid = [ ["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出: 1
示例 2:
css
输入: grid = [ ["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出: 3
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 300
grid[i][j]
的值为'0'
或'1'
代码
py
class Solution:
def numIslands(self, grid) -> int:
m, n = len(grid), len(grid[0])
def dfs(grid,i, j):
if not 0 <= i < m or not 0 <= j < n or grid[i][j] == '0':
return
grid[i][j] = '0'
dfs(grid, i - 1, j)
dfs(grid, i + 1, j)
dfs(grid, i, j - 1)
dfs(grid, i, j + 1)
cnt = 0
for i in range(m):
for j in range(n):
if grid[i][j] == '1':
dfs(grid,i,j)
cnt += 1
return cnt
这个解法同样使用了深度优先搜索(DFS)。
-
dfs
函数负责将当前位置(i, j)
所在的岛屿标记为已访问,递归地将相邻的陆地标记为已访问。- 如果当前位置越界或者是水域(
grid[i][j] == '0'
),直接返回。 - 将当前位置标记为已访问(
grid[i][j] = '0'
)。 - 递归地访问当前位置的上、下、左、右四个方向。
- 如果当前位置越界或者是水域(
-
主函数
numIslands
遍历整个网格,当发现岛屿(grid[i][j] == '1'
)时,调用dfs
函数将整个岛屿标记为已访问,并增加岛屿数量计数器cnt
。 -
最终返回岛屿数量
cnt
。
这个解法的思路是遍历整个网格,每当发现未访问的岛屿时,通过深度优先搜索将整个岛屿标记为已访问。遍历完整个网格后,所有岛屿都被访问过,最终返回岛屿数量。