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. SQL反模式学习笔记7 多态关联

    目标:引用多个父表 反模式:使用多用途外键.这种设计也叫做多态关联,或者杂乱关联. 多态关联和EAV有着相似的特征:元数据对象的名字是存储在字符串中的. 在多态关联中,父表的名字是存储在Issue_T ...

  2. java实验5

    实验一要求: 两人一组结对编程: 参考http://www.cnblogs.com/rocedu/p/6766748.html#SECDSA 结对实现中缀表达式转后缀表达式的功能 MyBC.java ...

  3. 《团队作业第一周》五小福团队作业——UNO

    <团队作业第一周>团队作业--UNO 一.团队展示 队员学号 队名:五小福 (真是个红红火火恍恍惚惚的队名)> 拟作的团队项目描述 基于安卓开发的有趣味性的UNO纸牌小游戏 队员风采 ...

  4. git 入门教程之删除文件

    删除文件 回忆一下文件的常见操作,新增文件,修改文件,删除文件等,新增和修改文件都单独讨论过,现在我们来研究一下如何删除文件. 你可能会说删除文件还不简单啊,直接 rm -rf <file> ...

  5. 动态规划——Valid Permutations for DI Sequence

    We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for &q ...

  6. jQuery 获取不到 kindeditor 内容 的解决方法

    错误写法 :  var content = $('#Content').val(); 正确写法: var content = $(document.getElementsByTagName(" ...

  7. Node.js_密码明文_密文_加密库_sha1

    加密库 sha1 加密模块,能够将指定 明文 加密成一个长度相等的 密文 let pwd = 'qwe123456'; const secret = sha1(pwd); 同样的明文,加密得到同样的密 ...

  8. [LeetCode] Minimum Distance Between BST Nodes 二叉搜索树中结点的最小距离

    Given a Binary Search Tree (BST) with the root node root, return the minimum difference between the ...

  9. ArcGIS AddIn 批量设置栅格图层背景色为透明

    protected override void OnClick() { // // TODO: Sample code showing how to access button host // Arc ...

  10. 19.3.25 sql查询语句

    1.单表查询:select * from 表名 where id = 111 2.查询表内数据并以id排序:select * from 表名 order by id (降序:desc/升序:asc) ...