剑指 Offer 13. 机器人的运动范围

解题思路:DFS

所谓的 DFS 是指:通过递归函数先朝着一个方向搜索到底,如果不符合题意就回溯至上一个节点,再沿着另一个方向搜索,直至找到答案。

剪枝是指:在 DFS 搜索中,我们需要标记哪些节点是已经是被访问过的,通常我的做法是使用一个数组 visited 来标记哪些节点被访问过,哪些节点没有被访问。

代码思路:

  • 当前元素在矩阵中的行列索引为 ij
  • DFS 递归中止条件:
    • 当行列索引:ij 越界,返回 0;这里面的越界无需考虑i < 0j < 0 的情况,因为我们只需要从位置[0,0] 向右,下 这两个方向去递归即可
    • 索引 ij 指向的元素数位和相加值超过了 k 时,返回 0
    • 当前元素已经被访问,即:visited == true,返回 0
  • DFS 递归过程:
    • visited[i][j] 标记为 true,表示该位置已经被访问过
    • 向下,右 两个放向递归
    • 最终返回 1 + 右下方向搜索的可达解总数
  • 获取一个数字的数位和:```java int getSum(int x){ int res = 0; while(x != 0){
    1. res += x % 10;
    2. x = x / 10;
    } return res; } ```

代码

Java

  1. class Solution {
  2. private int m;
  3. private int n;
  4. private int k;
  5. public int movingCount(int m, int n, int k) {
  6. this.m = m;
  7. this.n = n;
  8. this.k = k;
  9. boolean[][] visited = new boolean[m][n];
  10. return dfs(0,0,visited);
  11. }
  12. public int dfs(int i,int j,boolean[][] visited){
  13. if(i >= m || j >= n || getSum(i) + getSum(j) > k || visited[i][j]){
  14. return 0;
  15. }
  16. visited[i][j] = true;
  17. return 1 + dfs(i + 1,j,visited) + dfs(i,j + 1,visited);
  18. }
  19. public int getSum(int x){
  20. int res = 0;
  21. while(x != 0){
  22. res += x % 10;
  23. x = x / 10;
  24. }
  25. return res;
  26. }
  27. }

复杂度分析

  • 时间复杂度:O(MN)
    • 最差的情况下,机器人会遍历矩阵的所有位置,时间复杂度为:O(MN)
  • 空间复杂度:O(MN)
    • 开辟 visited 数组需要 M × N 的额外空间