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.html
Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination.java
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.git
Example 1github
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:函数
这道题让咱们遍历迷宫,可是与以往不一样的是,此次迷宫是有一个滚动的小球,这样就不是每次只走一步了,而是朝某一个方向一直滚,直到遇到墙或者边缘才停下来,博主记得貌似以前在手机上玩过相似的游戏。那么其实仍是要用 DFS 或者 BFS 来解,只不过须要作一些修改。先来看 DFS 的解法,用 DFS 的同时最好能用上优化,即记录中间的结果,这样能够避免重复运算,提升效率。这里用二维记忆数组 memo 来保存中间结果,而后用 maze 数组自己经过将0改成 -1 来记录某个点是否被访问过,这道题的难点是在于处理一直滚的状况,其实也不难,有了方向,只要一直在那个方向上往前走,每次判读是否越界了或者是否遇到墙了便可,而后对于新位置继续调用递归函数,参见代码以下:post
解法一:优化
class Solution { public: vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}}; bool hasPath(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) {int m = maze.size(), n = maze[0].size(); vector<vector<int>> memo(m, vector<int>(n, -1)); return helper(maze, memo, start[0], start[1], destination[0], destination[1]); } bool helper(vector<vector<int>>& maze, vector<vector<int>>& memo, int i, int j, int di, int dj) { if (i == di && j == dj) return true; if (memo[i][j] != -1) return memo[i][j]; bool res = false; int m = maze.size(), n = maze[0].size(); maze[i][j] = -1; for (auto dir : dirs) { int x = i, y = j; while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] != 1) { x += dir[0]; y += dir[1]; } x -= dir[0]; y -= dir[1]; if (maze[x][y] != -1) { res |= helper(maze, memo, x, y, di, dj); } } return memo[i][j] = res; } };
一样的道理,对于 BFS 的实现须要用到队列 queue,在对于一直滚的处理跟上面相同,参见代码以下:url
解法二:spa
class Solution { public: bool hasPath(vector<vector<int>>& maze, vector<int>& start, vector<int>& destination) { if (maze.empty() || maze[0].empty()) return true; int m = maze.size(), n = maze[0].size(); vector<vector<bool>> visited(m, vector<bool>(n, false)); vector<vector<int>> dirs{{0,-1},{-1,0},{0,1},{1,0}}; queue<pair<int, int>> q; q.push({start[0], start[1]}); visited[start[0]][start[1]] = true; while (!q.empty()) { auto t = q.front(); q.pop(); if (t.first == destination[0] && t.second == destination[1]) return true; for (auto dir : dirs) { int x = t.first, y = t.second; while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] == 0) { x += dir[0]; y += dir[1]; } x -= dir[0]; y -= dir[1]; if (!visited[x][y]) { visited[x][y] = true; q.push({x, y}); } } } return false; } };
Github 同步地址:
https://github.com/grandyang/leetcode/issues/490
相似题目:
参考资料:
https://leetcode.com/problems/the-maze/
https://leetcode.com/problems/the-maze/discuss/97081/java-bfs-solution
https://leetcode.com/problems/the-maze/discuss/97112/Short-Java-DFS-13ms-Solution