0%

机器人的运动范围


题目:

题解:

解题所需前提:

1、深度优先遍历

  • 解题思路:本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS)+ 剪枝 解决。

    • 深度优先搜索: 可以理解为暴力法遍历矩阵中所有字符串可能性。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
    • 剪枝: 在搜索中,遇到 这条路不可能和目标字符串匹配成功 的情况(例如:此矩阵元素和目标字符不同、此元素已被访问),则应立即返回,称之为 可行性剪枝
  • 复杂度分析:

    设矩阵行列数分别为 M, N 。

    时间复杂度 O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN) 。
    空间复杂度 O(MN) : 最差情况下,visited 内存储矩阵所有单元格的索引,使用 O(MN) 的额外空间。

  • 代码:

    • 普通版(未使用位数和规则)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // 深度优先遍历,普通
      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);
      }

      private int dfs(int a, int b, int m, int n, int k, boolean[][] visited) {
      if (a >= 0 && a < m && b >= 0 && b < n
      && (a % 10 + a / 10 + a / 100 + b % 10 + b / 10 + b / 100) <= k
      && visited[a][b] == false) {
      visited[a][b] = true;
      // 1是(0,0)位置,只需递归他右面和下面的即可
      return 1 + dfs(a + 1, b, m, n, k, visited) + dfs(a, b + 1, m, n, k, visited);
      }else return 0;
      }

      }
    • 复杂版(使用位数和规则)

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      // 深度优先遍历,复杂(找到位数和的规律,不需要每次计算,直接递归即可),第一种的优化
      class Solution2 {
      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, 0, 0);
      }
      // 当前元素在矩阵中的行列索引 i 和 j ,两者的数位和 si, sj
      public int dfs(int i, int j, int si, int sj) {
      if(i >= m || j >= n || k < si + sj || visited[i][j]) return 0;
      visited[i][j] = true;
      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);
      }
      }

2、广度优先遍历

  • 解题思路:

  • 复杂度分析:

    设矩阵行列数分别为 M, N 。

    时间复杂度 O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN) 。
    空间复杂度 O(MN) : 最差情况下,visited 内存储矩阵所有单元格的索引,使用 O(MN) 的额外空间。

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 广度优先遍历
    class Solution3 {
    public int movingCount(int m, int n, int k) {
    boolean[][] visited = new boolean[m][n];
    int count = 0;
    LinkedList<int[]> queue = new LinkedList<>();
    queue.add(new int[] {0,0,0,0});
    while (queue.size() > 0) {
    int[] poll = queue.poll();
    int i = poll[0],j = poll[1],si = poll[2],sj = poll[3];
    if (i >= m || j >= n || si + sj > k || visited[i][j]) continue;
    visited[i][j] = true;
    count++;
    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 count;
    }

    }