labuladong大佬的python版本,推荐大嘎关注公众号。
二维矩阵的DFS代码框架
def dfs(self,grid,i,j,visited:bool):
m, n =len(grid), len(grid[0])
# 越界条件
if i < 0 or j < 0 or i >= m or j >= n:
return
#遍历过(i,j)
if visited(i,j):
return
#前序,进入节点(i,j)
visited[i][j] =True
self.dfs(grid, i + 1, j)#下
self.dfs(grid, i, j + 1)#右
self.dfs(grid, i - 1, j)#上
self.dfs(grid, i, j - 1)#左
#后序,离开节点(i,j)
#visited[i][j] =True
一、力扣 200.岛屿数量 NC109 岛屿数量
#主函数,计算岛屿数量
def numIslands(self, grid: List[List[str]]) -> int:
#从 (i, j) 开始,将与之相邻的陆地都变成海水
def dfs(grid,i,j):
m, n =len(grid), len(grid[0])
# 越界条件
if i < 0 or j < 0 or i >= m or j >= n or grid[i][j] == '0':
return
#将 (i, j) 变成海水
grid[i][j] ='0'
#是陆地的话就淹没上下左右的陆地
dfs(grid, i + 1, j)
dfs(grid, i, j + 1)
dfs(grid, i - 1, j)
dfs(grid, i, j - 1)
m, n =len(grid), len(grid[0])
res=0
#遍历 grid
for i in range(m):
for j in range(n):
#每发现一个岛屿,岛屿数量加一
if grid[i][j] == '1':
res +=1
#然后使用 DFS 将岛屿淹了
dfs(grid,i,j)
return res
二、封闭岛屿的数量
将四周边缘的陆地变为海洋后,再进行(一)的操作
class Solution:
def closedIsland(self, grid: List[List[int]]) -> int:
def dfs(grid,i,j):
m, n =len(grid), len(grid[0])
if i < 0 or j < 0 or i >= m or j >= n or grid[i][j] == 1:
return
#将 (i, j) 变成海水
grid[i][j] =1
dfs(grid, i + 1, j)
dfs(grid, i, j + 1)
dfs(grid, i - 1, j)
dfs(grid, i, j - 1)
m, n =len(grid), len(grid[0])
for i in range(m):
dfs(grid,i, 0)
#使用defs(i,-1)错误
dfs(grid,i, n-1)
for j in range(n):
dfs(grid,0, j)
dfs(grid,m-1, j)
res=0
for i in range(m):
for j in range(n):
if grid[i][j] == 0:
res +=1
dfs(grid,i,j)
return res
三、NC185 岛屿的最大面积
在回溯时保存每块岛屿的陆地数量,然后在主函数求max(res,dfs)
class Solution:
def maxAreaIsland(self , grid: List[List[int]]) -> int:
# write code here
def dfs(grid,i,j):
if i>=m or j>=n or i<0 or j<0 or grid[i][j] == 0:
return 0
grid[i][j] = 0
#若是陆地,则return+1;若是海洋,则在之前就return 0,所以最后return的就是每块岛屿的陆地数量,即面积
return dfs(grid,i+1,j) + dfs(grid,i-1,j) + dfs(grid,i,j+1) + dfs(grid,i,j-1) + 1
m,n = len(grid),len(grid[0])
res = 0
for i in range(m):
for j in range(n):
if grid[i][j] == 1:
res = max(res,dfs(grid,i,j))
return res
四、1905. 统计子岛屿
把grid2中是陆地但grid1是海洋的地方变为海洋,然后计算grid2中岛屿数量
class Solution:
def countSubIslands(self, grid1: List[List[int]], grid2: List[List[int]]) -> int:
def dfs(grid,i,j):
if i<0 or j<0 or i>=m or j>=n or grid[i][j]==0:return
grid[i][j] = 0
dfs(grid,i-1,j)
dfs(grid,i,j-1)
dfs(grid,i+1,j)
dfs(grid,i,j+1)
m, n =len(grid1), len(grid1[0])
res = 0
for i in range(m):
for j in range(n):
if grid1[i][j] ==0 and grid2[i][j]== 1:
#grid2[i][j]=0
# 不能用这个语句是因为如例一,如果按照上面两行算的话,grid[5][4]没被淹掉,就也算一个子岛屿了,
dfs(grid2,i,j)
for i in range(m):
for j in range(n):
if grid2[i][j] == 1:
res += 1
dfs(grid2,i,j)
return res
五、694 不同的岛屿数量(力扣会员题,俺不是)
对于形状相同的岛屿,如果从同一起点出发,dfs函数遍历的顺序肯定是一样的。 分别用1,2,3,4代表上下左右,用-1,-2,-3,-4代表上下左右的撤销,则遍历顺序就可以记录,例如:2,4,1,-1,-4,-2
void dfs(int[][] grid, int i, int j, StringBuilder sb, int dir) {
int m = grid.length, n = grid[0].length;
if (i < 0 || j < 0 || i >= m || j >= n
|| grid[i][j] == 0) {
return;
}
// 前序遍历位置:进入 (i, j)
grid[i][j] = 0;
sb.append(dir).append(',');
dfs(grid, i - 1, j, sb, 1); // 上
dfs(grid, i + 1, j, sb, 2); // 下
dfs(grid, i, j - 1, sb, 3); // 左
dfs(grid, i, j + 1, sb, 4); // 右
// 后序遍历位置:离开 (i, j)
sb.append(-dir).append(',');
}
int numDistinctIslands(int[][] grid) {
int m = grid.length, n = grid[0].length;
// 记录所有岛屿的序列化结果
HashSet<String> islands = new HashSet<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] == 1) {
// 淹掉这个岛屿,同时存储岛屿的序列化结果
StringBuilder sb = new StringBuilder();
// 初始的方向可以随便写,不影响正确性
dfs(grid, i, j, sb, 666);
islands.add(sb.toString());
}
}
}
// 不相同的岛屿数量
return islands.size();
}