【leetCode】 - 不同路径

125 阅读2分钟

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

今天开始做BFS和DFS相关的题目,在开始之前有必要先了解一下BFS和DFS,我们拿矩阵进行举例:

  • BFS:广度优先遍历

    • 我们总是获取周围数据,随后再获取下一层
  • DFS:深度优先遍历

    • 我们总是获取更下层的数据直到遇到边界,随后再查询周围数据

题目

62. 不同路径

解析

这个题目应该算是这类题目最简单的类型之一了,图给好了限定也只有简单的往下往右。根据指导思想:

  • 从左上到右下算一次

我们可以通过一步一步地走,走到头算一次,算完汇总的方式,递归地来完成我们的代码:

 public static int uniquePaths(int m, int n) {
     boolean[][] visit = new boolean[m][n];
     return r(0,0,m-1,n-1,visit);
 }
 ​
 public static int r(int x,int y,int limitX,int limitY,boolean[][] visit){
     if(x==limitX && y == limitY) return 1;
     if( x>limitX || x<0 || y>limitY || y<0 || visit[x][y]) return 0;
     visit[x][y] = true;
     int down =  r(x,y+1,limitX,limitY,visit);
     int right = r(x+1,y,limitX,limitY,visit);
     visit[x][y] = false;
     return down+right;
 }

结果:超时

跟DP中超时的原因一样,过多地递归造成了不必要的麻烦,我们来考虑一下重复子问题的情况:

  • 假设我们现在走到了(k,j)的位置

那么,其实无论我们之前是走到哪里的,实际上从(k,j)出发到右下,我们的步数是相同的。

也就是说,我们可以将这个结果保存下来。

通过这个思路,我们改进上述的代码:

 public static int uniquePaths(int m, int n) {
     int[][] visit = new int[m][n];
     visit[m-1][n-1] = 1;
     return r(0,0,m-1,n-1,visit);
 }
 ​
 public static int r(int x,int y,int limitX,int limitY,int[][] visit){
         if( x>limitX || x<0 || y>limitY || y<0) return 0;
         if(visit[x][y]!=0) return visit[x][y];
         visit[x][y] = r(x,y+1,limitX,limitY,visit)+r(x+1,y,limitX,limitY,visit);
         return visit[x][y];
 }

执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户

内存消耗:35 MB, 在所有 Java 提交中击败了91.10%的用户

注意我们用了一点小trick:

  • 我们将(m-1,n-1)设置为1,省掉了一行if判断,代码也更美观。
  • 通过inline variable,省掉了两个用来临时存储的变量。