1、判断一个迷宫是否有出口
这个题目是我自己编的,leetcode上并没有这样的题目。为了锻炼自己的DFS,这个题目应该还是比较简单的,用深搜就可以完成,和之前做的max area of island有异曲同工之妙。
poll出迷宫问题:
如图所示的迷宫,0代表可以走,1代表有墙。要求从左上角到右下角是否有一条路可以走完。如何判断这个迷宫内是否有路。代码如下:
1 boolean res = false; 2 int[] dest; 3 int[][] grid; 4 boolean[][] visited; 5 public boolean can(int[][] grid, int[] start, int[] dest){ 6 boolean[][] visited = new boolean[grid.length][grid[0].length]; 7 this.dest = dest; 8 this.grid = grid; 9 this.visited = visited; 10 helper(start[0],start[1]); 11 return res; 12 } 13 14 private void helper(int i, int j) { 15 if ( i == dest[0] && j == dest[1] ) res=true; 16 visited[i][j] = true; 17 if ( cango(i-1,j) ) helper(i-1,j); 18 if ( cango(i+1,j) ) helper(i+1,j); 19 if ( cango(i,j-1) ) helper(i,j-1); 20 if ( cango(i,j+1) ) helper(i,j+1); 21 } 22 23 public boolean cango(int i, int j){ 24 if ( i < 0 || j < 0 || i >= grid.length || j >= grid.length) return false; 25 if ( grid[i][j] == 1 || visited[i][j] ) return false; 26 return true; 27 }
start数组时起始位置,end数组是终止位置。注意visited数组必不可少,记录走过的位置,已经走过的就不能再走了,否则就会陷入死循环。
这里先用一个cango函数来判断下一步是否可走,其实可以进行合并,简化一下:
1 boolean res = false; 2 int[] dest; 3 int[][] grid; 4 boolean[][] visited; 5 public boolean can(int[][] grid, int[] start, int[] dest){ 6 boolean[][] visited = new boolean[grid.length][grid[0].length]; 7 this.dest = dest; 8 this.grid = grid; 9 this.visited = visited; 10 newhelper(start[0],start[1]); 11 return res; 12 } 13 14 private void newhelper(int i, int j ){ 15 if ( i < 0 || j < 0 || i >= grid.length || j >= grid.length) return ; 16 if ( grid[i][j] == 1 || visited[i][j] ) return ; 17 if ( i == dest[0] && j == dest[1] ) res=true; 18 visited[i][j] = true; 19 newhelper(i-1,j); 20 newhelper(i+1,j); 21 newhelper(i,j-1); 22 newhelper(i,j+1); 23 }
我自己测试了几组情况,是正确的。不知道其他的情况是不是正确。
2、记录迷宫正确路径
现在问题变成这样,首先判断迷宫中能否有正确的道路,如果有的话,找出最短的那个道路。
因为要保存道路,所以一定要用一个数据结构来保存路径,栈是最好的。因为栈后进先出的特性,使得栈很适合数据的迭代。这里用两个栈来简单做一下,第一个栈stack1保存节点的行,第二个栈保存节点的列,两个栈就确定一个节点。
因为找的是最短路径,所以可以使用BFS算法。