题目描述

image.png

解题思路

详细解法🔗

DFS

此题和矩阵中的路径解题思路一致,但此题只需要向下和向右递归。

  1. int m, n, k;
  2. boolean[][] visited;
  3. public int movingCount(int m, int n, int k) {
  4. this.m = m;
  5. this.n = n;
  6. this.k = k;
  7. visited = new boolean[m][n];
  8. // 从 (0,0) 开始
  9. return dfs(0, 0, 0, 0);
  10. }
  11. /**
  12. * dfs深搜
  13. * 时间复杂度 O(MN)O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN)O(MN) 。
  14. * 空间复杂度 O(MN)O(MN) : 最差情况下,Set visited 内存储矩阵所有单元格的索引,使用 O(MN)O(MN) 的额外空间。
  15. *
  16. * @param i 代表此时的x
  17. * @param j 代表此时的y
  18. * @param si 此时x的位和
  19. * @param sj 此时y的位和
  20. * @return
  21. */
  22. public int dfs(int i, int j, int si, int sj) {
  23. // 越界或者已经访问过
  24. if (i >= m || j >= n || k < si + sj || visited[i][j]) return 0;
  25. visited[i][j] = true; // 访问过
  26. return 1 + dfs(i + 1, j, (i + 1) % 10 == 0 ? si - 8 : si + 1, sj) + dfs(i, j + 1, si, (j + 1) % 10 == 0 ? sj - 8 : sj + 1);
  27. }

BFS

BFS思路和DFS思路相差不大,只是BFS将下边和右边的元素入队之后在进行判断。

  1. /**
  2. * bfs搜索
  3. *
  4. * @param m
  5. * @param n
  6. * @param k
  7. * @return
  8. */
  9. public int movingCount(int m, int n, int k) {
  10. int res = 0; // 表示机器人可以走动结果
  11. Queue<int[]> queue = new LinkedList<>(); // 队列,记录遍历过的数组
  12. queue.offer(new int[]{0, 0, 0, 0});
  13. boolean[][] visited = new boolean[m][n]; // 表示是否走过
  14. while (!queue.isEmpty()) {
  15. int[] poll = queue.poll();
  16. int i = poll[0], j = poll[1], si = poll[2], sj = poll[3];
  17. if (i >= m || j >= n || k < si + sj || visited[i][j]) continue; // 越界或者相加大于k,或者访问过的,直接跳过
  18. visited[i][j] = true;
  19. res++;
  20. queue.offer(new int[]{i + 1, j, (i + 1) % 10 == 0 ? si - 8 : si + 1, sj}); // 下边元素入栈
  21. queue.offer(new int[]{i, j + 1, si, (j + 1) % 10 == 0 ? sj - 8 : sj + 1}); // 右边元素入栈
  22. }
  23. return res;
  24. }