1 题目描述
2. 算法分析
本题可使用 深度优先搜索(DFS) 或 广度优先搜索(BFS) 解决。
方法一、DFS
1.1 思路
- 思路理解:朝一个方向搜到底,然后再回溯。
- 剪枝:
- 算法解析:
- 递归参数:当前元素的矩阵索引i , j,两者的数位和
si
,sj
- 终止条件:1. 行列索引到头了。2. 数位和超出目标。3. 当前元素访问过了。
- 递归过程:
- 1.先标记当前单元格,并判断终止条件
- 2. 向下、右递归。
- 解释一下为啥是向下、向右:因为由上图可知,机器人可以到达的地方必定是一个等腰直角三角形,一定可以通过向下和向右到达。
- 返回值:1 + 向下递归结果 + 向右递归结果
关于两者的数位和
si
,sj的详细说明:
这里si并非是直接通过求当前树的数位和得到的
而是通过通过上一位的数位和,进行+1变换得到的,既然+1,就会出现两个情况
发生进位:这种情况,si = si - 8;
没有发生进位: si = si + 1;
因此才得到我们下面递归使用的式子:
- (i + 1) % 10 != 0 ? si + 1 : si- 8
1.2 代码
class Solution {
int m;
int n;
int k;
boolean[][] visited;
public int movingCount(int m, int n, int k) {
this.m = m;
this.n = n;
this.k = k;
this.visited = new boolean[m][n];
return dfs(0,0,0,0);
}
public int dfs(int i, int j, int si, int sj){
if(i >= m || j >= n || si +sj > k || visited[i][j])
return 0;
//当前方格满足条件
visited[i][j] = true; //代表访问过了
//(i+1) % 10 != 0 ? si+1 : si- 8 这个是在求向下递归后的数位变化
return 1 + dfs(i + 1,j,(i+1) % 10 != 0 ? si+1 : si- 8,sj)
+ dfs(i,j + 1,si,(j+1) % 10 != 0 ? sj + 1 : sj- 8);
}
}
1.3 结果
方法二、BFS
2.1 算法思路
- 思路理解:BFS就是平铺过去进行判断,不是DFS先朝一个方向到底。通常利用队列实现广度优先遍历
- 终止条件:队列为空就代表结束
- 递归过程:(弹1 ,加 2)
- 1. 将第一个单元格加入队列,然后弹出,
- 2. 进行判断:1. 行列索引到头了。2. 数位和超出目标。3. 当前元素访问过了。
- 3. 标记当前单元格被访问
- 4. 加入当前单元格的下、右单元格入队。
2.2 代码
class Solution {
public int movingCount(int m, int n, int k) {
//下面是bfs
boolean[][] visited = new boolean[m][n];
int res = 0;
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[] {0,0,0,0});
while(queue.size() > 0){
int[] temp = queue.poll();
int i = temp[0];
int j = temp[1];
int si = temp[2];
int sj = temp[3];
if(i >= m || j >= n || (si + sj) > k || visited[i][j]) //不满足条件,进行下次循环
continue;
//满足条件
visited[i][j] = true;
res++;
queue.add(new int[]{i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj});
queue.add(new int[]{i, j + 1, si , (j + 1) % 10 != 0 ? sj + 1 : sj - 8});
}
return res;
}
}
2.3 测试结果