二进制矩阵中的最短路径
难度:
标签:
题目描述
给你一个 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
代码结果
运行时间: 115 ms, 内存: 16.6 MB
/*
* 思路:
* 1. 使用Java Stream API不能直接用于BFS算法,但我们可以在过程中使用Stream来处理集合数据。
* 2. 其余逻辑与传统Java实现类似。
*/
import java.util.LinkedList;
import java.util.Queue;
import java.util.stream.IntStream;
public class SolutionStream {
public int shortestPathBinaryMatrix(int[][] grid) {
int n = grid.length;
if (grid[0][0] != 0 || grid[n - 1][n - 1] != 0) {
return -1;
}
int[][] directions = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{0, 0, 1});
grid[0][0] = 1;
while (!queue.isEmpty()) {
int[] current = queue.poll();
int row = current[0];
int col = current[1];
int length = current[2];
if (row == n - 1 && col == n - 1) {
return length;
}
IntStream.range(0, directions.length).forEach(i -> {
int newRow = row + directions[i][0];
int newCol = col + directions[i][1];
if (newRow >= 0 && newRow < n && newCol >= 0 && newCol < n && grid[newRow][newCol] == 0) {
queue.offer(new int[]{newRow, newCol, length + 1});
grid[newRow][newCol] = 1;
}
});
}
return -1;
}
}
解释
方法:
这个题解使用的是宽度优先搜索(BFS)算法来寻找从矩阵左上角到右下角的最短路径。首先,如果起点即grid[0][0]为1,则直接返回-1,因为起点不通畅。接着,使用一个队列q来存储需要探索的坐标,初始时只有起点[0, 0]。然后用一个二维数组mark来记录已经访问过的坐标,避免重复访问。接下来,进行BFS,每次从队列中取出一个坐标,检查它的8个方向上的相邻坐标,如果相邻坐标是0且未被访问过,则将其加入队列,并标记为已访问。当到达终点时,返回当前的步数。如果遍历完所有可达的坐标后仍未到达终点,则返回-1。
时间复杂度:
O(m*n)
空间复杂度:
O(m*n)
代码细节讲解
🦆
在题解中,为什么在初始检查时需要确认起点grid[0][0]是否为1,且为什么这会导致直接返回-1?
▷🦆
题解提及使用宽度优先搜索(BFS),能否解释为什么这种搜索策略适合用于找到最短路径?
▷🦆
题解中提到每次处理当前坐标的8个方向,为何选择检查所有8个方向而不是仅相邻的4个方向?
▷🦆
如果在某个方向上的单元格已经被标记为已访问,为什么还需要检查该单元格的值是否为0?
▷