一、题目
地上有一个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
提示:
- 1 <= n,m <= 100
- 0 <= k <= 20
补充:
- 测试要点:全域可达、(0,0)
其他:
- 优化:实现向右和向下即可,因为所有节点连通。
二、解决
1、BFS
思路:
方向 :(优化)
任何一个格子可以从任意一个方向进入,那么接下来只能往其他三个方向走,因为往回走就重复了。但实际上只要沿着两个方向走就可以,一个是向右,一个向下。
附-BFS代码模板:
public List<List<Integer>> BFS(TreeNode root) {
List<List<Integer>> allResults = new ArrayList<>();
if (root == null) return allResults;
Queue<TreeNode> nodes = new LinkedList<>();
nodes.add(root);
while (!nodes.isEmpty()) {
int levelSize = nodes.size();
List<Integer> results = new ArrayList<>();
for (int i = 0; i < levelSize; i++) {
TreeNode currNode = nodes.poll();
results.add(currNode.val);
if (currNode.left != null) nodes.add(currNode.left);
if (currNode.right != null) nodes.add(currNode.right);
}
allResults.add(results);
}
return allResults;
}
过程:
代码:
class Solution {
public int movingCount(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
int res = 0;
Queue<int[]> queue = new LinkedList<>();
queue.add(new int[]{0, 0});
while (!queue.isEmpty()) {
int[] dir = queue.poll();
int i = dir[0], j = dir[1];
if (i >= m || j >= n || divAndSum(i)+divAndSum(j) > k || visited[i][j]) continue;
visited[i][j] = true;
res++;
queue.add(new int[]{i + 1, j});
queue.add(new int[]{i, j + 1});
}
return res;
}
private int divAndSum(int x) {
int sum = 0;
while (x != 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
}
时间复杂度:
O
(
M
N
)
O(MN)
O(MN),M为网格长度,N为网格宽度。
空间复杂度:
O
(
M
N
)
O(MN)
O(MN)
2、DFS
思路:
附-DFS代码模板:
public List<Integer> dfs(Node root, int curLayer, List<Integer> result) {
// 终止条件
if (root == null || curlayer > n) return result; // 数据非法
if (curLayer.val == true) { // 满足条件
result.add(xxx); // xxx: node.val / curlayer / path
return result;
}
if (canCutBranch()) return result;
visited[root] = true; // 标记:处理当前顶点,记录为已访问
for (Node next : root) { // 遍历与当前顶点相邻的所有未访问顶点
visited[next] = true;
result.add(xxx) // 标记更改: 修改result/path/其他
dfs(next, curLayer + 1, result)
visited[next] = false;
result.remove(xxx) // 恢复更改: 还原result/path/其他
}
return result;
}
代码:
class Solution {
int m, n, 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);
}
public int dfs(int i, int j) {
if (i >= m || j >= n || divAndSum(i)+divAndSum(j) > k || visited[i][j]) return 0;
visited[i][j] = true;
return 1 + dfs(i + 1, j) + dfs(i, j + 1);
}
private int divAndSum(int x) {
int sum = 0;
while (x != 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
}
时间复杂度:
O
(
M
N
)
O(MN)
O(MN),M为网格长度,N为网格宽度。
空间复杂度:
O
(
M
N
)
O(MN)
O(MN)