题目
题目描述:给你一个 n x n 的二进制矩阵 grid 中,返回矩阵中最短 畅通路径 的长度。如果不存在这样的路径,返回 -1 。
二进制矩阵中的 畅通路径 是一条从 左上角 单元格(即,(0, 0))到 右下角 单元格(即,(n - 1, n - 1))的路径,该路径同时满足下述要求:
- 路径途经的所有单元格都的值都是 0 。
- 路径中所有相邻的单元格应当在 8 个方向之一 上连通(即,相邻两单元之间彼此不同且共享一条边或者一个角)。
畅通路径的长度 是该路径途经的单元格总数。
示例 1:
输入:grid = [[0,1],[1,0]]
输出:2
示例 2:
输入:grid = [[0,0,0],[1,1,0],[1,1,0]]
输出:4
示例 3:
输入:grid = [[1,0,0],[1,1,0],[1,1,0]]
输出:-1
提示:
n == grid.length
n == grid[i].length
1 <= n <= 100
grid[i][j] 为 0 或 1
思路
对于“最短路径”问题,首先应该想到的就是BFS。这里顺便记录一下一般什么情况用BFS,什么情况用DFS:
1. 当要找到所有可能解中最短的时,BFS会更高效。因为BFS是同时尝试所有解,当走到某一步已经得出正确解时,该解就是最短路径。而DFS是每次只尝试一个解,所以在走完所有解之前,DFS无法得知到底哪一个是最优解。
2. 当要求所有解时,DFS空间效率更高。从上面的对比也可以看出。
Python3代码
这里用了python标准库collections中的deque(双向队列)来实现BFS。
from collections import deque
class Solution:
def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
n = len(grid)
# 先处理特殊情况
if grid[0][0] or grid[-1][-1]:
return -1
if n == 1:
return 1
directions = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]
que = deque()
visited = set() # 已访问过的元素位置(避免重复访问)
que.appendleft((0, 0))
visited.add((0, 0))
cnt = 1
while que:
for _ in range(len(que)): # 一个for循环就相当于一步,即一次BFS
x, y = que.pop()
for di in directions:
new_x = x + di[0]
new_y = y + di[1]
if 0 <= new_x < n and 0 <= new_y < n and grid[new_x][new_y] == 0 and (new_x, new_y) not in visited:
if new_x == n - 1 and new_y == n - 1:
return cnt + 1
que.appendleft((new_x, new_y))
visited.add((new_x, new_y))
cnt += 1
return -1