Java
不同路径 III
https://leetcode-cn.com/problems/unique-paths-iii/
使用哈密尔顿路径的方法解决。
图的深度优先遍历,在遍历时通过left变量记录所有可走的方块有没有被遍历了,如果发现全部遍历过了,并且是在出口了,那么就认为我们找到了一条哈密尔顿路径,返回1,这样多个遍历路径合并的最终结果就是问题的解。有个比较神奇的地方,就是为啥只使用一次深度优先遍历就能找到所有路径?这应该归功于深度优先遍历的特点,可以尝试把深度优先遍历的遍历树画出来,每一个叶子结点到根结点的路径就是我们深度遍历到不同终点的路径了,而每个叶子结点之间的遍历互不影响~
本算法我认为有以下几点是比较特别的:
本算法对递归的使用、图的深度优先遍历、图的建模和对哈密尔顿路径的理解都是不错的锻炼。
还可以尝试把所有哈密尔顿路径输出。
class Solution { boolean[][] isVisited; // 访问数组 int[][] grid; // 格子的引用 int R, C; // 行数,列数 int start, end; // 开始位置,结束位置 int[][] dir4 = { // 上,下,左,右 4方向变量 {1,0}, {0,-1}, {0,1}, {-1,0} }; public int uniquePathsIII(int[][] grid) { this.grid = grid; R = grid.length; // 行 C = grid[0].length; // 列 isVisited = new boolean[R][C]; int left = 0; // 扫描整个地图,判断一共有多少个可以走的格子,获取起点和终点 for (int i = 0; i < R; i++) { for (int j = 0; j < C; j++) { if (grid[i][j] == 0) { left++; } else if (grid[i][j] == 1) { start = i * C + j;left++; } else if (grid[i][j] == 2) { end = i * C + j;left++; } } } // 深度优先遍历来获取路径数量 return dfs(start, left); } private int dfs(int v, int left) { int x = v / C; int y = v % C; isVisited[x][y] = true; left--; if (left == 0) { isVisited[x][y] = false; // 回溯,给其他路径留活路 if(v == end) { return 1; } return 0; // 找到了一条哈密尔顿路径 } int res = 0; // 获取相邻顶点 for (int[] ints : dir4) { int x1 = x + ints[0]; int y1 = y + ints[1]; if (x1 >= 0 && y1 >= 0 && x1 < R && y1 < C && grid[x1][y1] != -1 && !isVisited[x1][y1]) { res += dfs(x1 * C + y1, left); } } isVisited[x][y] = false; // 回溯 return res; } }