There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolling up, down, left or right, but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction.

Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination.

The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. You may assume that the borders of the maze are all walls. The start and destination coordinates are represented by row and column indexes.

Example 1

Input 1: a maze represented by a 2D array

0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (4, 4) Output: true
Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right.
Example 2 Input 1: a maze represented by a 2D array 0 0 1 0 0
0 0 0 0 0
0 0 0 1 0
1 1 0 1 1
0 0 0 0 0 Input 2: start coordinate (rowStart, colStart) = (0, 4)
Input 3: destination coordinate (rowDest, colDest) = (3, 2) Output: false
Explanation: There is no way for the ball to stop at the destination.
Note:
There is only one ball and one destination in the maze.
Both the ball and the destination exist on an empty space, and they will not be at the same position initially.
The given maze does not contain border (like the red rectangle in the example pictures), but you could assume the border of the maze are all walls.
The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100.
  • Search in the four possible directions when coming to a stopping point (i.e. a new starting point).
  • Keep track of places that you already started at in case you roll back to that point.
 public class Solution {
public boolean hasPath(int[][] maze, int[] start, int[] destination) {
boolean[][] startedHere = new boolean[maze.length][maze[0].length]; // mark visited starting points
return dfs(maze, startedHere, start, destination);
} private boolean dfs(int[][] maze, boolean[][] startedHere, int[] start, int[] destination) {
if (startedHere[start[0]][start[1]]) return false;
if (Arrays.equals(start, destination)) return true; startedHere[start[0]][start[1]] = true; // in case we roll back to a point we already started at BiPredicate<Integer, Integer> roll = (rowInc, colInc) -> {
int row = start[0], col = start[1]; // init new start row and col
while (canRoll(maze, row + rowInc, col + colInc)) {
row += rowInc;
col += colInc;
}
return dfs(maze, startedHere, new int[]{row, col}, destination); // pass in new start to dfs
}; if (roll.test(1, 0)) return true; // roll up
if (roll.test(0, 1)) return true; // roll right
if (roll.test(-1, 0)) return true; // roll down
if (roll.test(0, -1)) return true; // roll left return false; // return false if no paths led to destination
} private boolean canRoll(int[][] maze, int row, int col) {
if (row >= maze.length || row < 0 || col >= maze[0].length || col < 0) return false; // stop at borders
return maze[row][col] != 1; // stop at walls (1 -> wall)
}
}

UPDATE: Also including one without using BiPredicate on every recursive call since it runs faster

 public class Solution {

     private static final int[] DIRECTIONS = { 0, 1, 0, -1, 0 };

     public boolean hasPath(int[][] maze, int[] start, int[] destination) {
boolean[][] startedHere = new boolean[maze.length][maze[0].length];
return dfs(maze, startedHere, start, destination);
} private boolean dfs(int[][] maze, boolean[][] startedHere, int[] start, int[] destination) {
if (startedHere[start[0]][start[1]]) return false;
if (Arrays.equals(start, destination)) return true; startedHere[start[0]][start[1]] = true; for (int i = 0; i < DIRECTIONS.length - 1; i++) {
int[] newStart = roll(maze, start[0], start[1], DIRECTIONS[i], DIRECTIONS[i + 1]);
if (dfs(maze, startedHere, newStart, destination)) return true;
} return false;
} private int[] roll(int[][] maze, int row, int col, int rowInc, int colInc) {
while (canRoll(maze, row + rowInc, col + colInc)) {
row += rowInc;
col += colInc;
} return new int[]{row, col};
} private boolean canRoll(int[][] maze, int row, int col) {
if (row >= maze.length || row < 0 || col >= maze[0].length || col < 0) return false;
return maze[row][col] != 1; // 1 is a wall
}
}

Leetcode: The Maze(Unsolved locked problem)的更多相关文章

  1. Leetcode: Max Consecutive Ones II(unsolved locked problem)

    Given a binary array, find the maximum number of consecutive 1s in this array if you can flip at mos ...

  2. Leetcode: The Maze III(Unsolved Lock Problem)

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  3. [LeetCode] The Maze III 迷宫之三

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  4. [LeetCode] The Maze II 迷宫之二

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  5. [LeetCode] The Maze 迷宫

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  6. Leetcode: The Maze II

    There is a ball in a maze with empty spaces and walls. The ball can go through empty spaces by rolli ...

  7. Leetcode 365. Water and Jug Problem

    可以想象有一个无限大的水罐,如果我们有两个杯子x和y,那么原来的问题等价于是否可以通过往里面注入或倒出水从而剩下z. z =? m*x + n*y 如果等式成立,那么z%gcd(x,y) == 0. ...

  8. Leetcode: Find Permutation(Unsolve lock problem)

    By now, you are given a secret signature consisting of character 'D' and 'I'. 'D' represents a decre ...

  9. Leetcode 笔记 117 - Populating Next Right Pointers in Each Node II

    题目链接:Populating Next Right Pointers in Each Node II | LeetCode OJ Follow up for problem "Popula ...

随机推荐

  1. [转]Windows下Python多版本共存

    https://blog.csdn.net/dream_an/article/details/51248736 Windows下Python多版本共存 Python数据科学安装Numby,pandas ...

  2. AtCoder Grand Contest 030 (AGC030) C - Coloring Torus 构造

    原文链接https://www.cnblogs.com/zhouzhendong/p/AGC030C.html 题解 才发现当时是被题意杀了. 当时理解的题意是“对于任意的 (i,j) ,颜色 i 和 ...

  3. 一天带你入门到放弃vue.js(三)

    自定义指令 在上面学习了自定义组件接下来看一下自定义指令 自己新建的标签赋予特殊功能的是组件,而指定是在标签上使用类似于属性,以v-name开头,v-on,v-if...是系统指令! v-是表示这是v ...

  4. C - 树的统计Count - 树链剖分

    思路 :树剖模板,线段树维护即可. #include<bits/stdc++.h> using namespace std; #define MID int m = (l+r)/2 #de ...

  5. 机器学习入门之python实现图片简单分类

    小任务:实现图片分类 1.图片素材 python批量压缩jpg图片: PIL库 resize http://blog.csdn.net/u012234115/article/details/50248 ...

  6. [PA2014]Matryca

    [PA2014]Matryca 题目大意: 有一堵长度为\(n(n\le10^6)\)的墙需要刷漆,你有一把长度为\(k\)的刷子.墙和刷子都被均匀划分成单位长度的小格,刷子的每一格中都沾有某种颜色的 ...

  7. angular.isDate()

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. JDBC API 可滚动可编辑的结果集

    JDBC的API中的链接数据和创建statement并且执行读取ResultSet大家已经很熟悉了,这边介绍设置statement的属性使结果集可以移动并且进行编辑同步回数据库. Statement ...

  9. 输入、输出与Mad Libs 游戏

    name1=input('请输入一个名字:') name2=input('再输入一个名字:') time1=input('请输入一段时间:') print('{},是傻子,{},{}找不到小栗旬'.f ...

  10. (93)Wangdao.com_第二十六天_鼠标事件

    鼠标事件 与鼠标相关的事件,继承了 MouseEvent 接口 分类: click        按下鼠标(通常是按下主按钮)时触发.        mousedown 首先触发,mouseup 接着 ...