这是我参与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,省掉了两个用来临时存储的变量。