13. 机器人的运动范围
前言
- 由于本人入职准备,以及其他的杂七杂八事项,导致之前停更了好几天的leetcode做题。自己也非常愧疚,今日开始正常更新leetcode的每日一题。哎,生活难,难生活。
题目
- 地上有一个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。请问该机器人能够到达多少个格子?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
示例 1:
输入:m = 2, n = 3, k = 1
输出:3
示例 1:
输入:m = 3, n = 1, k = 0
输出:1
1.分析
- 首先根据题目大意,题中提供了一个m*n的矩阵。在矩阵上有一个机器人,每次机器人的移动方位只能是上下左右,以及边界不能移动。
- 在机器人移动的过程中,我们要保证题目中给出的条件,在满足条件的情况下,累加机器人走过了几个位置。最终返回的结果就是题目中要求的解体答案。
- 注:题目中明确给出了,条件[x,y]------x+y <= k,如果x,y分别为10位数,就要将x,y分解每个位置的数相加与k作比较。
2.设计
- 这种矩阵+条件,即为矩阵搜索问题,在遇到这类问题,一般的解决思路为BFS/DFS。也就是广度/深度优先搜索。
- 首先解决x,y中个位置数相加的结果。
- DFS—>DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
-
递归参数: 当前元素在矩阵中的行列索引 i 和 j ,两者的数位和 si, sj 。
-
终止条件: 当 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,返回 000 ,代表不计入可达解。
递推工作: -
标记当前单元格 :将索引 (i, j) 存入 Set visited 中,代表此单元格已被访问过。
-
搜索下一单元格: 计算当前元素的 下、右 两个方向元素的数位和,并开启下层递归 。
-
回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。
-
- BFS—>BFS 以“平推”的方式向前搜索,通常BFS的解决是利用辅助队列
-
初始化: 将机器人初始点 (0,0)(0, 0)(0,0) 加入队列 queue ;
迭代终止条件: queue 为空。代表已遍历完所有可达解。
迭代工作: -
单元格出队: 将队首单元格的 索引、数位和 弹出,作为当前搜索单元格。
-
判断是否跳过: 若 ① 行列索引越界 或 ② 数位和超出目标值 k 或 ③ 当前元素已访问过 时,执行 continue 。
-
标记当前单元格 :将单元格索引 (i, j) 存入 Set visited 中,代表此单元格 已被访问过 。
-
单元格入队: 将当前元素的 下方、右方 单元格的 索引、数位和 加入 queue 。
-
返回值: Set visited 的长度 len(visited) ,即可达解的数量。
-
3.实现
package com.iamasd;
import java.util.LinkedList;
import java.util.Queue;
/**
* @author EDZ
* 面试题13. 机器人的运动范围
*/
public class Test1 {
public static void main(String[] args) {
int i = movingCountBFS(16, 8, 4);
System.out.println(i);
}
/**
* BFS
* @param m
* @param n
* @param k
* @return
*/
public static int movingCountBFS(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
int res = 0;
Queue<int[]> queue= new LinkedList<int[]>();
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, (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;
}
/**
* DFS
* 利用辅助数组,标记自己走过的位置
* @param m
* @param n
* @param k
* @return
*/
public static int movingCountDFS(int m, int n, int k) {
boolean[][] visited = new boolean[m][n];
return dfs(0, 0, m, n, k, visited);
}
public static int dfs(int i,int j,int m,int n,int k,boolean[][] visited) {
if (i < 0 || i >= m || j < 0 || j >= n ||
(i/10 + i%10 + j/10 + j%10) > k ||
visited[i][j]) {
return 0;
}
visited[i][j] = true;
return dfs(i + 1, j, m, n, k, visited)
+ dfs(i - 1, j, m, n, k, visited)
+ dfs(i, j + 1, m, n, k, visited)
+ dfs(i, j - 1, m, n, k, visited) + 1;
}
}
4.总结
- 参考题解
- 读题,提取信息,遍历题库,找到类型,找到相应的解决方法。
- BFS—>借助队列
- DFS—>需要标记走过的路