Input: maze = [[“+”,“+”,“.”,“+”],[“.”,“.”,“.”,“+”],[“+”,“+”,“+”,“.”]], entrance = [1,2]
Output: 1
Explanation: There are 3 exits in this maze at [1,0], [0,2], and [2,3].
Initially, you are at the entrance cell [1,2].
第一时间想到的竟然是DFS而不是BFS。
下面来说明DFS是如何TLE的。虽然走不通,但是还是过一下。
DFS流程是下面这样的,
注意当前节点访问完,visited要变回false, 不然当前路径即使尝试失败,后面其他路径再想经过也会被堵。
int dfs(char[][] maze, int r, int c, boolean[][] visited, int steps) {
if(r < 0 || c < 0 || r > m || c > n) return 1000;
if(visited[r][c] || steps >= 1000) return 1000;
if(maze[r][c] == '+') return 1000;
if((r == 0 || r == m || c == 0 || c == n) && maze[r][c] == '.') {
steps ++;
return steps;
}
visited[r][c] = true;
steps ++;
int step1 = dfs(maze, r-1, c, visited, steps);
int step2 = dfs(maze, r, c+1, visited, steps);
int step3 = dfs(maze, r+1, c, visited, steps);
int step4 = dfs(maze, r, c-1, visited, steps);
visited[r][c] = false;
return Math.min(Math.min(step1, step2), Math.min(step3, step4));
}
从(17, 15)的"E"处出发,
如果是DFS,先探索从(16, 15)出发的路径的话,那可有得探索了,上面各种尝试,然而绕一大圈回来发现出口就在家门口。
那你说我改个方向,先探索从(17, 16)出发的路径,那么这个case是没问题了,entrance如果在第0列不还是会有这个问题么。
这种找最短路径,要突出一个短,按半径从小到大一圈一圈搜索,更容易快速找到出口。
BFS中有个问题是什么时候设置visited flag? 是访问到当前节点的时候,还是把下一节点装入queue的时候?
帮你们做了个实验,访问当前节点的时候steps++ 会 TLE,
为什么,因为装入queue就说明下一轮即将被访问,此时不设visited, 那该节点可能会被重复装入queue。
也可以不用visited二维数组,直接把访问过的地方设为“ + “ 也是一样的效果,不过就会改变原maze数组了。
public int nearestExit(char[][] maze, int[] entrance) {
int m = maze.length;
int n = maze[0].length;
Queue<int[]> queue = new LinkedList<>();
int steps = 0;
int[] direc = new int[]{-1, 0, 1, 0, -1};
boolean[][] visited = new boolean[m][n];
visited[entrance[0]][entrance[1]] = true;
queue.offer(entrance);
while(!queue.isEmpty()) {
steps ++;
int size = queue.size();
for(int s = 0; s < size; s++) {
int[] cur = queue.poll();
//visited[cur[0]][cur[1]] = true; //不要在这里设为true
for(int i = 0; i < 4; i++) {
int nextR = cur[0] + direc[i];
int nextC = cur[1] + direc[i+1];
if(nextR < 0 || nextR >= m || nextC < 0 || nextC >= n) continue;
if(visited[nextR][nextC]) continue;
if(maze[nextR][nextC] == '+') continue;
if(nextR == 0 || nextR == m-1 || nextC == 0 || nextC == n-1) return steps;
visited[nextR][nextC] = true; //装入queue时设为true,防止节点被重复装入queue
queue.offer(new int[]{nextR, nextC});
}
}
}
return -1;
}