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. 你好!酷痞Coolpy 之 Linux篇

    欢迎你进入酷痞的物联网世界.这里有着自由的空气和自然的气息.接下来我将告诉你如果一步步建立一个自己专属的物联网平台. 由于目前的酷痞的官方域名还没有通过备案所以现在用临时域名解说本说明. 最终酷痞的官 ...

  2. 关于input的检验问题

    写了很多小应用 但是 对于input有很多 相同的需求 在这里做一个总结 将用的多的校验方法 封装为方法 使用 1.只能输入正整数的校验 输入的时候同时校验 将字符类型的全部替换为空 <inpu ...

  3. ArrayList Vector

    100000条数据时:测了4次,分别是9ms/13ms:8ms/6ms:8ms/6ms:8ms/6ms[其中/前为ArrayList数据,/后为Vector数据]1000000条数据时:测了4次,分别 ...

  4. 洛谷P1379 八数码难题

    传送门 1.先用dfs枚举9!的全排列,存到hash数组里(类似离散化),因为顺序枚举,就不需要排序了 2.朴素bfs,判重就用二分找hash:如果发现当前状态=要求状态,输出步数结束程序 上代码 # ...

  5. 入门级----黑盒测试、白盒测试、手工测试、自动化测试、探索性测试、单元测试、性能测试、数据库性能、压力测试、安全性测试、SQL注入、缓冲区溢出、环境测试

    黑盒测试 黑盒测试把产品软件当成是一个黑箱子,只有出口和入口,测试过程中只要知道往黑盒中输入什么东西,知道黑盒会出来什么结果就可以了,不需要了解黑箱子里面是如果做的. 即测试人员不用费神去理解软件里面 ...

  6. vue-cli模拟后台数据交互

    作为一个前端入坑的妹子,在学习vue的道路上挣扎徘徊,由一开始的对vue一直蒙圈只知道双向数据绑定和一些'V-x'的指令,慢慢通过一个视频的学习渐渐入坑,对于我这个js基础不怎么好而且编程思维又不是很 ...

  7. Java虚拟机----垃圾回收与内存分配

    一.垃圾回收的对象: 在Java的运行时数据区中,程序计数器和虚拟机栈.本地方法栈是随着线程的生灭而生灭,栈当中栈帧的大小在编译的时候已知,在方法结束之后栈帧出栈,这部分的垃圾回收是明确的,因此需要讨 ...

  8. (71)Wangdao.com第十一天_JavaScript 数学对象 Math

    Math 对象 封装了数学相关的 属性和方法. 和其他对象不一样,Math 不是一个构造函数,所以不能 new 生成实例, 其所有属性和方法都必须在 Math 对象上调用. 静态属性 Math.PI ...

  9. BOM 浏览器对象模型_不超过 4 KB 的 document.cookie 对象

    注意: 客户端储存应该使用 Web storage API 和 IndexedDB,不推荐使用 Cookie document.cookie 对象 是服务器保存在浏览器的一小段文本信息 用于读写当前网 ...

  10. Java课程寒假之回答问题:如何将你的兴趣化为可以立足于社会的资本

    在学校的时候干过几次兼职,算是无聊时候的外快吧,有一次是去辅导机构,在考试期间监考学生,前后大概四个小时,最后拿了四十五并且管了一顿饭,不得不说,小学生是真的皮,考试的时候有的爱讲话,有的是写完之后开 ...