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

  

 

 

posted @ 2020-06-19 11:43  GumpYan  阅读(274)  评论(0编辑  收藏  举报