题目链接
迷宫中离入口最近的出口
题目描述
注意点
- maze[i][j] 要么是 ‘.’ ,要么是 ‘+’
- entrance.length == 2
- entrance 一定是空格子
- 出口的含义是 maze 边界上的空格子
- entrance格子不算出口
解答思路
- 广度优先遍历找到走i步时所能到达的所有节点位置(相同位置多次遍历需要排除,所以需要使用二维数组visited存储已经到达过的节点)。使用队列存储第i步所能到达的所有位置,先将入口入队,可以向上下左右四个方向进行移动(前提是未出界,移动的位置不是墙,移动的位置没有被遍历过),重复上述过程,直到找到出口或队列中没有元素为止
- 需要注意的是在移动到新的位置(x, y)将该位置添加到队列时也要同步将visted[x][y]标记为true,而不是出队时才标记,因为相同步数可能由上一步多个点到达该位置,可能会做多次入队出队操作(与一次入队出队操作相同),效率很低
代码
class Solution {public int nearestExit(char[][] maze, int[] entrance) {int res = 0;int row = maze.length;int col = maze[0].length;int[][] direction = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};boolean[][] visited = new boolean[row][col];Deque<int[]> deque = new ArrayDeque<>();deque.offerLast(new int[]{entrance[0], entrance[1]});visited[entrance[0]][entrance[1]] = true;while (!deque.isEmpty()) {int size = deque.size();for (int i = 0; i < size; i++) {int[] loc = deque.pollFirst();int x = loc[0], y = loc[1];if (isExport(x, y, row, col, entrance)) {return res;}// 朝着四个方向前进for (int j = 0; j < direction.length; j++) {int newX = x + direction[j][0], newY = y + direction[j][1];// 移动的格子未出界、不是墙、未遍历过if (newX >= 0 && newX < row && newY >= 0 && newY < col && maze[newX][newY] == '.' && !visited[newX][newY]) {deque.offerLast(new int[]{newX, newY});// 入队立马标记为已遍历,防止同一层遍历多次相同位置visited[newX][newY] = true;}}}res++;}return -1;}public boolean isExport(int x, int y, int row, int col, int[] entrance) {if (x == entrance[0] && y == entrance[1]) {return false;}return x == 0 || y == 0 || x == row - 1 || y == col - 1;}
}
关键点
- 入口不能作为出口
- 广度优先遍历的思想
- 在朝着四个方向前进时,哪些位置不能到达
- 在到达新位置时,入队的同时还要将visited标记为true