BFS-地图分析&岛屿数量
1.地图分析
解题思路
此题是一个标准的广度优先题目。
基本思路就是不断模拟从陆地向海洋扩张的最长距离:
查找初始所有陆地坐标,并进行判断是否为空或长度与grid大小一致,满足条件即输出-1
定义一个判断给定坐标值是否有效的辅助函数:isValid(x, y)
定义一个4向delta列表,用于从当前坐标生成新坐标,并初始化depth=-1
从当前陆地坐标列表开始向外扩张探索:
对于每个待搜索的陆地坐标,依次生成4个方向新的坐标值
若新坐标值尚未探索到,则加入到待探索列表tmp,并将其"填充"为陆地(即赋值为1),避免重复探索
若当前深度所有陆地周边仍有待探索的海洋(即tmp不为空),则继续探测
最后,需特殊考虑depth初值问题:由于陆地初始值是已有深度,当其探索一层后方可赋值为1,所以其初始值实际上应为-1.
class Solution: def maxDistance(self, grid: List[List[int]]) -> int: # m-行数,n-列数 m, n = len(grid), len(grid[0]) # 找到陆地坐标 nodes = [(i, j) for i in range(m) for j in range(n) if grid[i][j]] print(nodes) if not nodes or len(nodes)==m*n:#是否为纯陆地或纯海洋 return -1 # 判定指定坐标是否有效 def isValid(x, y): return 0<=x<m and 0<=y<n # 四个移动方向 delta = [(0, 1), (0, -1), (1, 0), (-1, 0)] depth = -1 while nodes: depth += 1 tmp = [] # 存储探索海洋目标 for x, y in nodes: # 对当前每个待探坐标分别处理4个方向 for d in delta: newx, newy = x+d[0], y+d[1] if isValid(newx, newy) and not grid[newx][newy]: tmp.append((newx, newy)) grid[newx][newy] = 1 # 已经探测到的改成陆地 nodes = tmp return depth
来看看细节:
grid = [[1,0,1],[0,0,0],[1,0,1]] m, n = len(grid), len(grid[0]) nodes = [(i, j) for i in range(m) for j in range(n) if grid[i][j]] print('nodes:', nodes) for x, y in nodes: print('x:', x) print('y:', y)
class Solution: def numIslands(self, grid: List[List[str]]) -> int: # 方向数组,它表示了相对于当前位置的 4 个方向的横、纵坐标的偏移量,这是一个常见的技巧 directions = [(-1, 0), (0, -1), (1, 0), (0, 1)] m = len(grid) # 特判 if m == 0: return 0 n = len(grid[0]) marked = [[False for _ in range(n)] for _ in range(m)] count = 0 for i in range(m): for j in range(n): if not marked[i][j] and grid[i][j] == '1': queue = deque() queue.append((i, j)) # 注意:这里要标记上已经访问过 marked[i][j] = True while queue: cur_x, cur_y = queue.popleft() for d in directions: new_i, new_j = cur_x + d[0], cur_y + d[1] # 如果不越界、没有被访问过、并且还要是陆地,我就继续放入队列,放入队列的同时, # 要记得标记已经访问过 if 0 <= new_i < m and 0 <= new_j <n and not marked[new_i][new_j] and grid[new_i][new_j] == '1': queue.append((new_i, new_j)) marked[new_i][new_j] = True count += 1 return count
以下是错误的,不知道为啥是错的
class Solution: def numIslands(self, grid: List[List[str]]) -> int: m, n = len(grid), len(grid[0]) # 找到陆地坐标 nodes = [(i, j) for i in range(m) for j in range(n) if grid[i][j]] print(nodes) delta = [(0, 1), (0, -1), (1, 0), (-1, 0)] count = 0 marked = [[False for _ in range(m)] for _ in range(n)] print(marked) while nodes: count += 1 tmp = [] for x, y in nodes: for d in delta: newx, newy = x+d[0], y+d[1] # 只要是陆地,且没有被访问过的,就可以使用 BFS 发现与之相连的陆地,并进行标记 if 0<=m<newx and 0<=n<newy and not marked[newx][newy] and grid[newx][newy]: tmp.append((newx, newy)) marked[newx][newy] = True nodes = tmp return count