二进制矩阵的最短路径
LeetCode
在一个 N × N 的方形网格中,每个单元格有两种状态:空(0)或者阻塞(1)。
一条从左上角到右下角、长度为 k 的畅通路径,由满足下述条件的单元格 C_1, C_2, …, C_k 组成:
相邻单元格 C_i 和 C_{i+1} 在八个方向之一上连通(此时,C_i 和 C_{i+1} 不同且共享边或角)
C_1 位于 (0, 0)(即,值为 grid[0][0])
C_k 位于 (N-1, N-1)(即,值为 grid[N-1][N-1])
如果 C_i 位于 (r, c),则 grid[r][c] 为空(即,grid[r][c] == 0)
返回这条从左上角到右下角的最短畅通路径的长度。如果不存在这样的路径,返回 -1 。
解决方案
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-in-binary-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
广度优先搜索
例如,在访问1时,会将2,5放到访问序列。
所以访问序列是:
注意:
- 访问队列的维护
- 访问标志位的维护
class Solution {
public int shortestPathBinaryMatrix(int[][] grid) {
// grid检测
if(grid == null || grid.length == 0){
return -1;
}
// 方向偏移量
// 左,左下,下...左上 共8个方向
int[][] direct = {{-1, 0}, {-1,1}, {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1, -1}};
// 待访问节点的队列
Queue<Pair<Integer,Integer>> queue = new LinkedList<>();
// 加入起始结点
queue.add(new Pair<Integer,Integer>(0,0));
//总距离
int distance = 0;
// 遍历队列
while(!queue.isEmpty()){
int size = queue.size();
distance ++;
// 遍历每层
while(size > 0){
size --;
// 获取第一个访问节点坐标
Pair<Integer,Integer> curPos = queue.poll();
int indexRow = curPos.getKey();
int indexCol = curPos.getValue();
//不可达或者已经被访问过
//因为被访问过的标记也是1
if(grid[indexRow][indexCol] == 1){
// 直接退出,如果访问过,访问时候子节点一定加入到了队列中。
continue;
}
//修改为1,标记成已经访问过
grid[indexRow][indexCol] = 1;
//到达目标点
if(indexRow == grid.length-1 && indexCol == grid[0].length-1){
return distance;
}
// - 没有到达终点
// - 当前节点没有被访问
//将与该节连接的节点放到访问队列中
for(int[] it : direct){
int newIndexRow = indexRow + it[0];
int newIndexCol = indexCol + it[1];
// 新坐标边界检测
if(newIndexRow < 0 || newIndexRow > grid.length-1 ||
newIndexCol < 0 || newIndexCol > grid[0].length-1 ){
continue;
}
// 注意已经被访问的节点,也会被加入到队列中。
queue.add(new Pair<Integer, Integer>(newIndexRow, newIndexCol));
}
}
}
// 没有到达终点,返回-1
return -1;
}
}