题目描述
地上有一个m行n列的方格,从坐标 [0,0]
到坐标 [m-1,n-1]
。一个机器人从坐标[0, 0]
的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。
例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例1:
输入:m = 2, n = 3, k = 1
输出:3
示例2:
输入:m = 3, n = 1, k = 0
输出:1
题解
从题目上来看,就是一个传统的带条件的搜索题目。很容易想到DFS或者BFS。两者目标都是遍历整个矩阵,不同点在于搜索顺序不同。DFS是朝一个方向走到底,再回退一步,走到底,再回退,以此类推(即,栈的结果);BFS 则是按照一排一排的方式向前搜索。
从优化的角度,虽然可以上下左右,但因为起始点在[0,0]
,所以只需要考虑向下和向右的情况即可。
DFS(java)
DFS
class Solution {
int max = 0;
public boolean into(int a, int b, int k) {
int count = 0;
while (a > 0) {
count += a % 10;
a = a / 10;
}
while (b > 0) {
count += b % 10;
b = b / 10;
}
if (count <= k) {
return true;
} else {
return false;
}
}
public void step(int a, int b, int m, int n, int k, int[][] flag) {
if (flag[a][b] == 1) return;
//判断右侧有无格子且根据k能否进入
if (a + 1 < m && into(a + 1 ,b ,k)) {
step(a + 1, b, m, n, k, flag);
}
//判断下侧有无格子且根据k能否进入
if (b + 1 < n && into(a, b + 1,k)) {
step(a, b + 1, m, n, k, flag);
}
flag[a][b] = 1;
max += 1;
}
public int movingCount(int m, int n, int k) {
int[][] flag = new int [m][n];
step(0, 0, m, n, k, flag);
return max;
}
}
复杂度分析
- 时间复杂度: O ( n ∗ m ) O(n*m) O(n∗m)
- 空间复杂度: O ( n ∗ m ) O(n*m) O(n∗m)
DFS2(java)
同样是DFS,但是写法明显优化很多。
class Solution {
public int movingCount(int m, int n, int k) {
//设置辅助数组
boolean[][] visited = new boolean[m][n];
//返回结果
return dfs(0, 0, m, n, k, visited);
}
public int dfs(int i, int j, int m, int n, int k, boolean[][] visited) {
//把所有限制条件用||来连接起来
if(i >= m || j >= n || k < getSum(i) + getSum(j) || visited[i][j]) {
return 0;
}
visited[i][j] = true;
// 每次返回值加一
return 1 + dfs(i + 1, j, m, n, k, visited) + dfs(i, j + 1, m, n, k, visited);
}
private int getSum(int a) {
int sum = a % 10;
int tmp = a / 10;
while(tmp > 0) {
sum += tmp % 10;
tmp /= 10;
}
return sum;
}
}
- 时间复杂度: O ( n ∗ m ) O(n * m) O(n∗m)
- 空间复杂度: O ( n ∗ m ) O(n * m) O(n∗m)
BFS(java)
贴一下bfs模板,以先进先出的方式对空间进行遍历。
while queue 不空:
cur = queue.pop()
for 节点 in cur的所有相邻节点:
if 该节点有效且未访问过:
queue.push(该节点)
按这个思路,写法如下
class Solution {
//计算数位之和
private int getSum(int a) {
int count = 0;
while (a > 0) {
count += a % 10;
a = a / 10;
}
return count;
}
public int movingCount(int m, int n, int k) {
// 辅助数组,默认值为false。(同int[][],默认为0)
boolean[][] visited = new boolean[m][n];
int res = 0;
//BFS
Queue<int[]> queue= new LinkedList<int[]>();
// 初始化,同new int[4]
queue.add(new int[] { 0, 0, 0, 0 });
while(queue.size() > 0) {
int[] x = queue.poll();
int i = x[0], j = x[1], si = x[2], sj = x[3];
if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;
visited[i][j] = true;
res ++;
//添加相邻位置
queue.add(new int[] { i + 1, j, getSum(i + 1), getSum(j) });
queue.add(new int[] { i, j + 1, getSum(i), getSum(j + 1) });
}
return res;
}
}
- 时间复杂度: O ( n ∗ m ) O(n * m) O(n∗m)
- 空间复杂度: O ( n ∗ m ) O(n * m) O(n∗m)