算法刷题自记录 | Leetcode1091. 二进制矩阵中的最短路径(BFS)

题目

题目描述:给你一个 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值