🚩传送门:力扣题目

题目

在二维网格 [LC]980. 不同路径 III - 图1 上,有[LC]980. 不同路径 III - 图2种类型的方格:

  • [LC]980. 不同路径 III - 图3表示起始方格。且只有一个起始方格。
  • [LC]980. 不同路径 III - 图4表示结束方格,且只有一个结束方格。
  • [LC]980. 不同路径 III - 图5表示我们可以走过的空方格。
  • [LC]980. 不同路径 III - 图6表示我们无法跨越的障碍。

返回在四个方向( 上、下、左、右 )上行走时,从起始方格到结束方格的不同路径的数目。

每一个无障碍方格都要通过一次,但是一条路径中不能重复通过同一个方格。

示例 1:

输入:[[1,0,0,0],[0,0,0,0],[0,0,2,-1]] 输出:2 解释:我们有以下两条路径:

  1. (0,0),(0,1),(0,2),(0,3),(1,3),(1,2),(1,1),(1,0),(2,0),(2,1),(2,2)
  2. (0,0),(1,0),(2,0),(2,1),(1,1),(0,1),(0,2),(0,3),(1,3),(1,2),(2,2)

解题思路:深搜

让我们尝试遍历每一个 [LC]980. 不同路径 III - 图7 方格,并在走过的方格里留下一个障碍。回溯的时候,我们要删除那些自己留下的障碍。
深搜所有的可能路径,对到达终点的路径判断是否已经全部路过了每一个 [LC]980. 不同路径 III - 图8 方格(即数组中不存在 [LC]980. 不同路径 III - 图9 方格),满足条件的全局变量 [LC]980. 不同路径 III - 图10[LC]980. 不同路径 III - 图11

复杂度分析

时间复杂度:[LC]980. 不同路径 III - 图12,其中[LC]980. 不同路径 III - 图13是这个二维网格行与列的大小。

空间复杂度:[LC]980. 不同路径 III - 图14

官方代码

  1. class Solution {
  2. int res;
  3. public int uniquePathsIII(int[][] grid) {
  4. if (grid == null || grid.length == 0) return 0;
  5. res = 0;
  6. // 找起点位置开始dfs
  7. for (int i = 0; i < grid.length; i++) {
  8. for (int j = 0; j < grid[i].length; j++) {
  9. if (grid[i][j] == 1) {
  10. dfs(grid, i, j);
  11. return res;
  12. }
  13. }
  14. }
  15. return res;
  16. }
  17. private void dfs(int[][] grid, int i, int j) {
  18. // 边界合法性检查
  19. if (i < 0 || i >= grid.length || j < 0 || j >= grid[i].length) return;
  20. // 判断能否跨越
  21. if (grid[i][j] == -1) return;
  22. // 遇到终点,判断当前路径是否满足要求
  23. if (grid[i][j] == 2) {
  24. // 检查是否还有未走的空格
  25. for (int k = 0; k < grid.length; k++) {
  26. for (int l = 0; l < grid[k].length; l++) {
  27. if (grid[k][l] == 0) return;
  28. }
  29. }
  30. res++;
  31. return;
  32. }
  33. // 对可行点(i,j)标记访问
  34. grid[i][j] = -1;
  35. // 定义四向搜索
  36. int[][] dir = new int[][]{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
  37. for (int k = 0; k < dir.length; k++) {
  38. dfs(grid,i+dir[k][0],j+dir[k][1]);
  39. }
  40. // 四向搜索完成,取消标记
  41. grid[i][j] = 0;
  42. }
  43. }