第十一章 图论 Part2
任务
200. 岛屿数量
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
思路
总的逻辑是,每遇到一个新的岛屿,就将计数加1,具体的遍历格子则使用dfs和bfs去遍历陆地,对于每一个格子,都进行dfs或bfs的遍历,
- 当前为水,不统计计数,继续下一个格子的处理
- 当前为已经遍历过的岛屿,不统计计数,继续下一个格子的处理
- 遇到新大陆(未访问过的大陆格子),则对该格子进行遍历以找到与该格子相关的整个岛屿
具体单个岛屿的遍历,实现既可以用dfs,也可以用bfs。
对于dfs,每遇到新的格子(未访问过的)且为陆地则标记并递归遍历,这里隐含着,如果遇到不是陆地的地方则进行下一个方向的处理。如此,可以访问一个整岛屿,将其相关格子标记为True。
对于bfs,实际与bfs同理,只是遍历的流程是按照层去遍历,也是遍历一整个岛屿,将整个岛屿的格子标记为True。需要注意的点是,在每次加入队列时,都需要标记格子为True,原因是为了不重复访问,节省时间,具体更详细的原因可以去看第十一章 图论 Part1的内容。
下面给出dfs和bfs解决这个问题的代码
class Solution: def numIslands(self, grid: List[List[str]]) -> int: visited = [[False] * len(grid[0]) for _ in range(len(grid))] result = 0 for i in range(len(grid)): #以每个格子为起点进行遍历 for j in range(len(grid[0])): if visited[i][j]==False and grid[i][j] == '1': #为新大陆时,累加结果 result += 1 #self.dfs(grid,visited,i,j) #按深度优先遍历标记某岛屿 self.bfs(grid,visited,i,j) #按广度优先遍历标记某岛屿 return result def dfs(self,grid,visited,x,y): dir = [(1,0),(0,1),(-1,0),(0,-1)] #逆时针四个方向 visited[x][y] = True # 由调用者(包含外部和自身)保证了该格子为访问过的陆地! for i in range(4): nextX = x + dir[i][0] nextY = y + dir[i][1] if nextX < 0 or nextY<0 or nextX>=len(grid) or nextY>=len(grid[0]): continue if visited[nextX][nextY] == False and grid[nextX][nextY] == '1': self.dfs(grid,visited,nextX,nextY) from collections import deque def bfs(self,grid,visited,x,y): dir = [(1,0),(0,1),(-1,0),(0,-1)] #逆时针四个方向 que = deque() que.append((x,y)) visited[x][y] = True while(que): curX,curY = que.popleft() for i in range(4): nextX = curX + dir[i][0] nextY = curY + dir[i][1] if nextX < 0 or nextY<0 or nextX>=len(grid) or nextY>=len(grid[0]): continue if visited[nextX][nextY] == False and grid[nextX][nextY] == '1': que.append((nextX,nextY)) visited[nextX][nextY] =True
695. 岛屿的最大面积
给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。
计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。
思路
如果理解了上一题,本题就可以直接解决,本题求的是岛屿面积,累计的值就是某一个岛屿的面积,就在dfs或者bfs中累计,然后在主函数中取最大的岛屿面积即可。
下面给出dfs和bfs的方法
class Solution: def __init__(self): self.count = 0 def maxAreaOfIsland(self, grid: List[List[int]]) -> int: visited = [[False] * len(grid[0]) for _ in range(len(grid))] result = 0 for i in range(len(grid)): #以每个格子为起点进行遍历 for j in range(len(grid[0])): if visited[i][j]==False and grid[i][j] == 1: #为新大陆时,累加结果 self.count = 0 #self.dfs(grid,visited,i,j) #按深度优先遍历标记某岛屿 self.bfs(grid,visited,i,j) #按深度优先遍历标记某岛屿 result = max(result,self.count) return result def dfs(self,grid,visited,x,y): dir = [(1,0),(0,1),(-1,0),(0,-1)] #逆时针四个方向 visited[x][y] = True # 由调用者(包含外部和自身)保证了该格子为访问过的陆地! self.count += 1 for i in range(4): nextX = x + dir[i][0] nextY = y + dir[i][1] if nextX < 0 or nextY<0 or nextX>=len(grid) or nextY>=len(grid[0]): continue if visited[nextX][nextY] == False and grid[nextX][nextY] == 1: #未访问过的陆地则继续访问(直到遍历完整个单独的岛屿) self.dfs(grid,visited,nextX,nextY) from collections import deque def bfs(self,grid,visited,x,y): dir = [(1,0),(0,1),(-1,0),(0,-1)] #逆时针四个方向 que = deque() que.append((x,y)) visited[x][y] = True self.count += 1 while(que): curX,curY = que.popleft() for i in range(4): nextX = curX + dir[i][0] nextY = curY + dir[i][1] if nextX < 0 or nextY<0 or nextX>=len(grid) or nextY>=len(grid[0]): continue if visited[nextX][nextY] == False and grid[nextX][nextY] == 1: #未访问过的陆地则继续访问(直到遍历完整个单独的岛屿) que.append((nextX,nextY)) visited[nextX][nextY] =True self.count+=1
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构