#99. 岛屿数量
深度优先搜索:
每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
本题思路:用遇到一个没有遍历过的节点陆地,计数器就加一,然后把该节点陆地所能遍历到的陆地都标记上。在遇到标记过的陆地节点和海洋节点的时候直接跳过。 这样计数器就是最终岛屿的数量。
def dfs(grid, visited, x, y):
if visited[x][y] or grid[x][y] == 0:
return # 终止条件:访问过的节点 或者 遇到海水
visited[x][y] = True # 标记访问过
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]] # 四个方向(上右下左的顺序)
for dx, dy in directions:
nextx = x + dx
nexty = y + dy
if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]): # 检查是否越界
dfs(grid, visited, nextx, nexty)
def main():
n, m = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(n)]
visited = [[False] * m for _ in range(n)]
result = 0
for i in range(n):
for j in range(m):
if not visited[i][j] and grid[i][j] == 1:
result += 1 # 遇到没访问过的陆地,+1
dfs(grid, visited, i, j) # 将与其链接的陆地都标记上 True
print(result)
if __name__ == "__main__":
main()
广度优先搜索:
from collections import deque
def bfs(grid, visited, x, y):
# 使用deque实现队列
queue = deque([(x, y)])
visited[x][y] = True # 加入队列后立即标记为已访问
directions = [[0,1],[1,0],[0,-1],[-1,0]]
while queue:
curx, cury = queue.popleft() # 从队列中取出当前位置
for dx, dy in directions: # 遍历四个方向
nextx, nexty = curx + dx, cury + dy
# 检查新位置是否在网格内
if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):
# 如果新位置未被访问且是陆地,则加入队列并标记为已访问
if not visited[nextx][nexty] and grid[nextx][nexty] == 1:
queue.append((nextx, nexty))
visited[nextx][nexty] = True
def main():
n, m = map(int, input().split())
# 使用列表推导式初始化网格和访问记录
grid = [list(map(int, input().split())) for _ in range(n)]
visited = [[False] * m for _ in range(n)]
result = 0
# 遍历网格,找到未访问的陆地,计算陆地区域数量
for i in range(n):
for j in range(m):
if not visited[i][j] and grid[i][j] == 1:
result += 1
bfs(grid, visited, i, j)
print(result)
if __name__ == "__main__":
main()
DFS写法:
dfs只处理下一个节点,即在主函数遇到岛屿就计数为1,dfs处理接下来的相邻陆地
def dfs(grid, visited, x, y):
# 定义四个方向
directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]
if visited[x][y] or grid[x][y] == 0: # 终止条件:访问过的节点 或者 遇到海水
return
visited[x][y] = True # 标记访问过
global count # 使用全局变量count,因为需要在dfs调用之间共享状态
count += 1
for dx, dy in directions:
nextx = x + dx
nexty = y + dy
# 检查新坐标是否越界
if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]):
dfs(grid, visited, nextx, nexty) # 递归调用dfs
def find_max_island_area(grid):
# 获取网格的行数和列数
n = len(grid)
m = len(grid[0])
# 初始化访问记录矩阵
visited = [[False] * m for _ in range(n)]
# 初始化结果变量
result = 0
for i in range(n): # 遍历网格
for j in range(m):
if not visited[i][j] and grid[i][j] == 1: # 如果是未访问的陆地
count = 0 # 重置计数器
dfs(grid, visited, i, j) # 执行深度优先搜索
result = max(result, count) # 更新最大陆地区域大小
return result
BFS写法:
from collections import deque
class Solution:
def maxAreaOfIsland(self, grid):
# 定义四个方向
self.dir = [[0, 1], [1, 0], [0, -1], [-1, 0]]
# 初始化结果变量
result = 0
# 遍历网格,寻找未访问的陆地
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
# 使用bfs算法计算陆地区域大小
area = self.bfs(grid, i, j)
result = max(result, area)
return result
def bfs(self, grid, x, y):
# 检查坐标是否越界
if x < 0 or x >= len(grid) or y < 0 or y >= len(grid[0]):
return 0
# 访问记录集合
visited = [[False] * len(grid[0]) for _ in range(len(grid))]
# 初始化队列
queue = deque([(x, y)])
# 初始化陆地区域计数
count = 1
while queue:
# 从队列中取出当前坐标
xx, yy = queue.popleft()
# 标记当前坐标为已访问
visited[xx][yy] = True
# 遍历四个方向
for dx, dy in self.dir:
nextx, nexty = xx + dx, yy + dy
# 如果新坐标在网格内且未被访问过且是陆地
if 0 <= nextx < len(grid) and 0 <= nexty < len(grid[0]) and not visited[nextx][nexty] and grid[nextx][nexty] == 1:
# 将新坐标加入队列
queue.append((nextx, nexty))
# 标记新坐标为已访问
visited[nextx][nexty] = True
# 更新陆地区域计数
count += 1
return count
# 示例使用
# 假设有一个网格
grid = [
[1, 1, 0, 0, 0],
[1, 1, 0, 0, 0],
[0, 0, 0, 1, 1],
[0, 0, 0, 1, 1]
]
# 创建Solution实例并调用maxAreaOfIsland方法
solution = Solution()
print(solution.maxAreaOfIsland(grid))