leetcode 1926. Nearest Exit from Entrance in Maze(迷宫最近的出口)

在这里插入图片描述
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].

  • You can reach [1,0] by moving 2 steps left.
  • You can reach [0,2] by moving 1 step up.
    It is impossible to reach [2,3] from the entrance.
    Thus, the nearest exit is [0,2], which is 1 step away.
    在这里插入图片描述
    给一个迷宫,“.“代表此路可走,”+“代表此路不通,
    给一个entrance的位置作为初始位置。
    从初始位置出发,走到迷宫的边界处,如果边界处是“.”, 就说明到达了出口,返回最短的路径。
    初始位置即使在边界处,也不能算作出口。
    如果不存在能走出去的路径,返回-1.
思路:

第一时间想到的竟然是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<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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蓝羽飞鸟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值