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));
}
来看看DFS为神马会TLE。
从(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 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; //不要在这里设为truefor(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,防止节点被重复装入queuequeue.offer(new int[]{nextR, nextC});}} }return -1;}