Leetcode广度优先搜索笔记3 二进制矩阵中的最短路径

本文介绍了如何利用广度优先搜索(BFS)解决一个二维二进制矩阵中最短畅通路径的问题。畅通路径要求从左上角到右下角,且所有经过的单元格值为0。通过示例展示了算法的实现,并分析了为什么选择BFS而非DFS。在广度优先搜索过程中,用队列存储路径,遇到终点则返回路径长度,否则不断尝试8个方向的相邻单元格,直到找到符合条件的路径或遍历完所有可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1091. 二进制矩阵中的最短路径:广度优先搜索解决矩阵中的路径寻找问题

给你一个 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

广度优先搜索解法:

畅通路径中,所有单元格的值必须为 0 且需要从 grid 左上角抵达右下角,同时本题另一个特殊之处在于需要考虑对角线在内的 8 个前进方向,而不是常规情况下的 4 个方向。

根据畅通路径的条件,首先进行简单判断:若左上或右下单元格值为1,不存在畅通路径;若矩阵大小为 1×1 且其中单个元素为 0,畅通路径即为 1,即仅经过 (0, 0) 位置一个点。

题目要求寻找最短的畅通路径长度,适合使用广度优先搜索,同时尝试所有可能的情况,只要一种情况下到达路径重点,该情况即为最短畅通路径的情况。而深度优先搜索是每次完成一条路径的搜索,要想得到最短畅通路径需要完成所有可能路径的搜索后取最小,因此使用 BFS 更加高效。

使用队列完成广度优先搜索,起点 (0, 0) 首先入队,路径值为 1;对当前队列中的每个节点,判断其通过 8 个方向走到下一步后的位置,若下一步的位置即为终点,路径值加一并直接返回路径值即为最小的畅通路径长度;否则仍然需要继续判断下一个位置是否仍在矩阵内且其值为 0,若是则将下一个位置添加到队列中待后续搜索使用,需要将加入队列的位置处的值改为 1 以避免重复搜索同一个位置;对队列中现有元素的处理过程中,如果队列中某个位置的下一个位置符合继续搜索的条件,需要将当前路径长度加 1,通过 flag 进行记录,只要有一个位置的下一个位置符合条件,当前路径长度就需要加 1。

如果在搜索过程中到达终点位置,路径长度加 1 后直接返回;若正常退出广度优先搜索过程,代表不存在符合条件的畅通路径,返回 -1。

class Solution {
public:
    int directions[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
    int shortestPathBinaryMatrix(vector<vector<int>>& grid) {
        int n = grid.size();
        if(grid[0][0] == 1 || grid[n - 1][n - 1] == 1)
            return -1;
        if(n == 1 && grid[0][0] == 0)
            return 1; 
        queue<pair<int, int>> que;
        que.push({0, 0});
        grid[0][0] = 1;
        int ans = 1;
        while(!que.empty()){
            int size = que.size();
            bool flag = false;
            for(int i = 0; i < size; i++){
                auto p = que.front();
                que.pop();
                for(auto direction: directions){
                    int x = p.first + direction[0], y = p.second + direction[1];
                    if(x == n - 1 && y == n - 1){
                        ans++;
                        return ans;
                    }
                    if(x >= 0 && x < n && y >= 0 && y < n && grid[x][y] == 0){
                        que.push({x, y});
                        grid[x][y] = 1;
                        flag = true;
                    }
                }
            }
            if(flag)
                ans++;
        }
        return -1;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值