LeetCode 1162 地图分析 最短路径

1. 题目

你现在手里有一份大小为 n x n 的 网格 grid,上面的每个 单元格 都用 0 和 1 标记好了。其中 0 代表海洋,1 代表陆地,请你找出一个海洋单元格,这个海洋单元格到离它最近的陆地单元格的距离是最大的。如果网格上只有陆地或者海洋,请返回 -1。

我们这里说的距离是「曼哈顿距离」( Manhattan Distance):(x0, y0) 和 (x1, y1) 这两个单元格之间的距离是 |x0 - x1| + |y0 - y1|

2. 思路

  1. 单源最短路径
    本体可以视为每个海洋单元离陆地的最短路径的最大值,res=max(res,bfs(海洋单元格))
    最短路径:使用广度优先遍历算法,遍历图时,和遍历树的思路基本一致,将该时刻所能到达的点(树中为该节点的子节点,该题中为该点上下左右四个点)加入队列中,然后在下一个时刻从队列中取出,因为每个时间点只能走一步,在图中的表现每个点每次只会向周围点扩散一次,所以当队列最后为空时,则视为遍历完整个图,因为树时单向的,图时无向图,因此遍历时,需要记录该点是否被访问过,如果被访问直接跳过。
    时间复杂度为O(n^4)
  2. 多源最短路径
    因为该题中有多个海洋点,因此我们视为从每个陆地出发,寻找最远的海洋点。因此,我们将陆地视为源点,依次遍历陆地周围的所有海洋点,最后遍历到的海洋就时最远的海洋点。多源最短路径可以视为单源最短的第二层,也就是有一个超级源点的单源最短路径。

3. Code

1.单源最短路径

from queue import Queue
class Solution:
    def maxDistance(self, grid: List[List[int]]) -> int:
        n=len(grid)
        res=-1
        for i in range(n):
            for j in range(n):
				#遍历每个海洋点
                if grid[i][j]==0:
                    res=max(res,self.bfs(i,j,n,grid))
        return res
    def bfs(self,x,y,n,grid):
		#四个方向
        dir=[[-1,0],[1,0],[0,-1],[0,1]]
        deq=Queue()
        #记录每个点走的步数
		m={}
        deq.put([x,y])
        m[x*n+y]=0
        while not deq.empty():
            cur=deq.get()
            dx=cur[0]
            dy=cur[1]
            step=m[dx*n+dy]
			#到达陆地点,直接返回步数
            if grid[dx][dy]==1:
                return step
			#遍历四个方向
            for di in dir:
                nx=dx+di[0]
                ny=dy+di[1]
				#超出边界
                if nx<0 or nx>=n or ny<0 or ny>=n:
                    continue
                key=nx*n+ny
				#已经访问
                if key in m.keys():
                    continue
                deq.put([nx,ny])
                m[key]=step+1
        return -1
  1. 多源最短路径
from queue import Queue
class Solution:
    def maxDistance(self, grid: List[List[int]]) -> int:
        dir=[[-1,0],[1,0],[0,-1],[0,1]]
        n=len(grid)
        deq=Queue()
        m={}
        #将所有陆地放入队列,从每个陆地出发,求最远的海洋
        for i in range(n):
            for j in range(n):
                if grid[i][j]==1:
                    deq.put([i,j])
                    m[n*i+j]=0
        res=-1
        while not deq.empty():
            cur=deq.get()
            dx=cur[0]
            dy=cur[1]
            step=m[n*dx+dy]
            for di in dir:
                nx=dx+di[0]
                ny=dy+di[1]
                if nx<0 or nx>=n or ny<0 or ny>=n:
                    continue
				#跳过陆地点
                if grid[nx][ny]!=0:
                    continue
                grid[nx][ny]=step+1
                deq.put([nx,ny])
                m[nx*n+ny]=step+1
				#因为每一步都是在走海洋点的路径上,所以当前路径就是一条合法路径
                res=max(res,step+1)
        return res
posted @ 2022-01-29 15:55  流光之中  阅读(206)  评论(0编辑  收藏  举报