问题描述
在一个 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 。
示例 1:
输入:[[0,1],[1,0]]
输出:2
示例 2:
输入:[[0,0,0],[1,1,0],[1,1,0]]
输出:4
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shortest-path-in-binary-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
- 1、本题目是求最短路径,因此要使用BFS
- 2、仔细看示例,最左上角的格子已经算是1步了,这里有点误导性,要注意
- 3、按照BFS算法,使用队列来保存要访问的元素,每次循环对长度+1,比如第一轮循环就遍历左上角的格子的周围8个方向的格子,如果有0,则value设置为1,第二轮循环遍历长度为2的格子的八个方向,一次类推…
- 4、如果遍历的格子到了最右下角,则说明找到了最短距离,如果队列都为空了,并且还是不是最右下角格子,说明没有路径,返回-1
- 5、解题思路参考了:https://www.bilibili.com/video/av56067911/ 的部分讲解,实现部分没有细看,感兴趣的可以看看他的实现,或许比我实现得更优雅。
代码实现
public int shortestPathBinaryMatrix(int[][] grid) {
int gridLineNum = grid.length;
int gridColNum = grid[0].length;
if (grid[0][0] == 1 || grid[gridLineNum - 1][gridColNum - 1] == 1) {
return -1;
}
grid[0][0] = 1;
Queue<GridCell> visitCellQueue = new LinkedBlockingDeque<>();
visitCellQueue.add(new GridCell(0, 0, 1));
while (!visitCellQueue.isEmpty()) {
GridCell cellToCheck = visitCellQueue.poll();
checkEightDirectionForCell(cellToCheck,grid,visitCellQueue);
if (cellToCheck.getLine() == grid.length-1 && cellToCheck.getCol() == grid.length-1){
return cellToCheck.getValue();
}
}
return -1;
}
private void checkEightDirectionForCell(GridCell gridCell, int[][] grid, Queue<GridCell> visitCellQueue) {
//上
if (gridCell.getLine() - 1 >= 0 && grid[gridCell.getLine() - 1][gridCell.getCol()] == 0) {
grid[gridCell.getLine() - 1][gridCell.getCol()] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() - 1, gridCell.getCol(), grid[gridCell.getLine() - 1][gridCell.getCol()]));
}
//左上
if (gridCell.getLine() - 1 >= 0 && gridCell.getCol() - 1 >= 0 && grid[gridCell.getLine() - 1][gridCell.getCol() - 1] == 0) {
grid[gridCell.getLine() - 1][gridCell.getCol() - 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() - 1, gridCell.getCol() - 1, grid[gridCell.getLine() - 1][gridCell.getCol() - 1]));
}
//左
if (gridCell.getCol() - 1 >= 0 && grid[gridCell.getLine()][gridCell.getCol() - 1] == 0) {
grid[gridCell.getLine()][gridCell.getCol() - 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine(), gridCell.getCol(), grid[gridCell.getLine()][gridCell.getCol() - 1]));
}
//左下
if (gridCell.getLine() + 1 < grid.length && gridCell.getCol() - 1 >= 0 && grid[gridCell.getLine() + 1][gridCell.getCol() - 1] == 0) {
grid[gridCell.getLine() + 1][gridCell.getCol() - 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() + 1, gridCell.getCol() - 1, grid[gridCell.getLine() + 1][gridCell.getCol() - 1]));
}
//下
if (gridCell.getLine() + 1 < grid.length && grid[gridCell.getLine() + 1][gridCell.getCol()] == 0) {
grid[gridCell.getLine() + 1][gridCell.getCol()] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() + 1, gridCell.getCol(), grid[gridCell.getLine() + 1][gridCell.getCol()]));
}
//右下
if (gridCell.getLine() + 1 < grid.length && gridCell.getCol() + 1 < grid.length && grid[gridCell.getLine() + 1][gridCell.getCol() + 1] == 0) {
grid[gridCell.getLine() + 1][gridCell.getCol() + 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() + 1, gridCell.getCol() + 1, grid[gridCell.getLine() + 1][gridCell.getCol() + 1]));
}
//右
if (gridCell.getCol() + 1 < grid.length && grid[gridCell.getLine()][gridCell.getCol() + 1] == 0) {
grid[gridCell.getLine()][gridCell.getCol() + 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine(), gridCell.getCol() + 1, grid[gridCell.getLine()][gridCell.getCol() + 1]));
}
//右上
if (gridCell.getLine() - 1 >= 0 && gridCell.getCol() + 1 < grid.length && grid[gridCell.getLine() - 1][gridCell.getCol() + 1] == 0) {
grid[gridCell.getLine() - 1][gridCell.getCol() + 1] = gridCell.getValue() + 1;
visitCellQueue.add(new GridCell(gridCell.getLine() - 1, gridCell.getCol() + 1, grid[gridCell.getLine() - 1][gridCell.getCol() + 1]));
}
}
class GridCell {
private int line;
private int col;
private int value;
public int getLine() {
return line;
}
public void setLine(int line) {
this.line = line;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public GridCell(int line, int col, int value) {
this.line = line;
this.col = col;
this.value = value;
}
}