Leetcode——迷宫

1. 题目

由空地(用 0 表示)和墙(用 1 表示)组成的迷宫 maze 中有一个球。球可以途经空地向 上、下、左、右 四个方向滚动,且在遇到墙壁前不会停止滚动。当球停下时,可以选择向下一个方向滚动。

  • 给你一个大小为 m x n 的迷宫 maze ,以及球的初始位置 start 和目的地 destination
  • 其中 start = [startrow, startcol] 且 destination = [destinationrow, destinationcol] 。
  • 请你判断球能否在目的地停下:如果可以,返回 true ;否则,返回 false 。

你可以 假定迷宫的边缘都是墙壁(参考示例)。
在这里插入图片描述

2. 题解

(1)DFS

  • 用深度优先搜索对整颗搜索树进行遍历。
  • 从起始位置开始,每次选择一条路线进行搜索,并用一个二维布尔数组 visited 表示是否曾经到达过位置 (i, j)
  • 若在某一次搜索到位置 (i, j) 时,visited[i, j] = true,那么我们可以进行回溯,不必继续搜索下去。
class Solution {
    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        int row = maze.length;
        if (row == 0)
            return false;
        int col = maze[0].length;
        if (col == 0)
            return false;
        
        boolean[][] verify = new boolean[row][col];  //标记哪些节点被遍历过
        return dfs(maze, start, destination, verify);
    }

    public boolean dfs(int[][] maze, int[] start, int[] destination, boolean[][] verify) {
        //已搜索过的值不用继续判断,直接回溯
        if (verify[start[0]][start[1]])
            return false;
        if (start[0] == destination[0] && start[1] == destination[1]) 
            return true;
        
        verify[start[0]][start[1]] = true;          //标记当前节点已遍历过

        //定义四个方向
        int up = start[0] - 1;
        int down = start[0] + 1;
        int left = start[1] - 1;
        int right = start[1] + 1;

        //向上走,传入新的start,继续找它的上下左右每个方向节点
        while (up >= 0 && maze[up][start[1]] == 0)          
            up--;
        if (dfs(maze, new int[]{up + 1, start[1]}, destination, verify))		//继续找当前节点的上下左右节点
             return true;	                                                    //结束 while 时,说明当前点是墙壁或者超出边界,往回走一格,up+1

        //向下走
        while (down < maze.length && maze[down][start[1]] == 0)         
            down++;
        if (dfs(maze, new int[]{down - 1, start[1]}, destination, verify))	//继续找当前节点的上下左右节点
            return true;

        //向左走
        while (left >= 0 && maze[start[0]][left] == 0)          
            left--;
        if (dfs(maze, new int[]{start[0], left + 1}, destination, verify))	//继续找当前节点的上下左右节点
            return true;

         //向右走
        while (right < maze[0].length && maze[start[0]][right] == 0)          
            right++;
        if (dfs(maze, new int[]{start[0], right - 1}, destination, verify))	//继续找当前节点的上下左右节点
            return true;

        return false;       //如果遍历所有节点都未找到终点值,返回false
          
    }
}

简化一下代码:

class Solution {
    private int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
	//上,下,左,右
    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        int row = maze.length;
        if (row == 0)
            return false;
        int col = maze[0].length;
        if (col == 0)
            return false;
        
        boolean[][] verify = new boolean[row][col];  //标记哪些节点被遍历过
        return dfs(maze, start, destination, verify, row, col);
    }

    public boolean dfs(int[][] maze, int[] start, int[] destination, boolean[][] verify, int row, int col) {
        //已搜索过的值不用继续判断,直接回溯
        if (verify[start[0]][start[1]])
            return false;
        if (start[0] == destination[0] && start[1] == destination[1]) 
            return true;
        
        verify[start[0]][start[1]] = true;          //标记当前节点已遍历过

        int x = start[0];
        int y = start[1];
        for (int[] direction : directions) {
                int newX = x + direction[0];
                int newY = y + direction[1];
                while (newX >= 0 && newX < row && newY >= 0 && newY < col && maze[newX][newY] == 0) {
                    // 只要是空格,就一路往前走,直到碰到墙壁
                    newX += direction[0];
                    newY += direction[1];
                }
                //结束 while 时,说明当前点是墙壁或者超出边界,往回走一格
                newX -= direction[0];
                newY -= direction[1];

                //这个for循环记录从起点开始能够到达的每一个节点,然后再逐一计算这些节点的每一个节点
                //继续循环各个方向,如果这个停止点是曾经访问过的,则忽略
                if (dfs(maze, new int[]{newX, newY}, destination, verify, row, col))	//继续找当前节点的上下左右节点
                     return true;
            }

      
        return false;       //如果遍历所有节点都未找到终点值,返回false
          
    }
}

(2)BFS

  • 记录从起点开始能够到达的每一个节点(因为只有触碰到边界或者墙才会停下来)
  • 然后再记录每一个节点的所有节点
  • 判断是否有节点为目标节点,有则返回true,无则返回false;
public class Solution {
    private int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
	//上,下,左,右
    public boolean hasPath(int[][] maze, int[] start, int[] destination) {
        int rows = maze.length;
        if (rows == 0) return false;
        int cols = maze[0].length;
        if (cols == 0) return false;
        return bfs(maze, start, destination, rows, cols);
    }

    private boolean bfs(int[][] maze, int[] start, int[] destination, int rows, int cols) {
        boolean[][] visited = new boolean[rows][cols];	//判断该节点是否来过
        Queue<int[]> queue = new LinkedList<>();		//存储节点坐标
        queue.add(start);
        visited[start[0]][start[1]] = true;
        while (!queue.isEmpty()) {
            int[] curPoint = queue.poll();  // 获取当前坐标
            int x = curPoint[0];
            int y = curPoint[1];
            if (x == destination[0] && y == destination[1]) {
                return true;
            }
            for (int[] direction : directions) {
                int newX = x + direction[0];
                int newY = y + direction[1];
                while (newX >= 0 && newX < rows && newY >= 0 && newY < cols && maze[newX][newY] == 0) {
                    // 只要是空格,就一路往前走,直到碰到墙壁
                    newX += direction[0];
                    newY += direction[1];
                }
                //结束 while 时,说明当前点是墙壁或者超出边界,往回走一格
                newX -= direction[0];
                newY -= direction[1];
                //这个for循环记录从起点开始能够到达的每一个节点,然后再逐一计算这些节点的每一个节点
                // 如果这个停止点是曾经访问过的,则忽略
                if (!visited[newX][newY]) {
                    queue.add(new int[]{newX, newY});
                    visited[newX][newY] = true;
                }
            }
        }
        return false;
    }
}
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
插件名字叫leetcode editor,可以解决在上班时想刷leetcode但又不想直接打开leetcode界面太扎眼或者无法debug的问题。你可以在IDEA的plugins中搜索并下载leetcode editor插件。 插件的下载地址是https://plugins.jetbrains.com/plugin/12132-leetcode-editor。 下载并安装插件后,你可以在IDEA的File -> Settings -> Tools -> Leetcode Plugin***com作为网址选项。此外,你还可以选择代码类型,包括Java、Python、C、Python3、C、C#、JavaScript、Ruby、Swift、Go、Scala、Kotlin、Rust、PHP。你需要输入登录名和密码来登录leetcode账号,并可以设置临时文件的存放目录和HTTP Proxy。 如果你想自定义代码模板,可以参考该插件提供的自定义代码模板文档(https://github.com/shuzijun/leetcode-editor/blob/master/doc/CustomCode.md)。通过这个插件,你可以方便地在IDEA中刷leetcode,并享受更好的调试体验。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [好用的idea插件leetcode editor【详细安装指南】](https://blog.csdn.net/weixin_45988401/article/details/129170239)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [IDEA插件系列(112):LeetCode Editor插件——LeetCode编辑器](https://blog.csdn.net/cnds123321/article/details/119859448)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yawn__

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

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

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

打赏作者

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

抵扣说明:

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

余额充值