【刷题记录】20.机器人的运动范围

98 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

题目来源: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。请问该机器人能够到达多少个格子?

示例 1:

输入:m = 2, n = 3, k = 1

输出:3

示例 2:

输入:m = 3, n = 1, k = 0

输出:1

提示:

1 <= n,m <= 100

0 <= k <= 20

二、思路分析:

  1. 大体思路:广度优先搜索
  2. 假设把行坐标和列坐标数位之和大于 k的格子作为障碍物,就可以看做是一道搜索题目
  3. 把数对10取余,就能知道对应的个位数是多少,等价于将数的十进制位向右移了一位,并且删除了个位数,类似于二进制的移位
  4. 不断重复移位操作,直到数为0为止

三、AC 代码:

  class Solution {
        public int movingCount(int m, int n, int k) {
            if (k == 0) {
                return 1;
            }
            Queue<int[]> queue = new LinkedList<int[]>();
            int[] rightArray = {0, 1};
            int[] downArray = {1, 0};
            boolean[][] pointer = new boolean[m][n];
            queue.offer(new int[]{0, 0});
            pointer[0][0] = true;
            int result = 1;
            while (!queue.isEmpty()) {
                int[] cell = queue.poll();
                int x = cell[0], y = cell[1];
                for (int i = 0; i < 2; ++i) {
                    int tx = rightArray[i] + x;
                    int ty = downArray[i] + y;
                    if (tx < 0 || tx >= m || ty < 0 || ty >= n || pointer[tx][ty] || get(tx) + get(ty) > k) {
                        continue;
                    }
                    queue.offer(new int[]{tx, ty});
                    pointer[tx][ty] = true;
                    result++;
                }
            }
            return result;
        }

        private int get(int x) {
            int res = 0;
            while (x != 0) {
                res += x % 10;
                x /= 10;
            }
            return res;
        }
    }

思路二: 递推

    class Solution {
        public int movingCount(int m, int n, int k) {
            if (k == 0) {
                return 1;
            }
            boolean[][] pointer = new boolean[m][n];
            int result = 1;
            pointer[0][0] = true;
            for (int i = 0; i < m; ++i) {
                for (int j = 0; j < n; ++j) {
                    if ((i == 0 && j == 0) || get(i) + get(j) > k) {
                        continue;
                    }
                    if (i - 1 >= 0) {
                        pointer[i][j] |= pointer[i - 1][j];
                    }
                    if (j - 1 >= 0) {
                        pointer[i][j] |= pointer[i][j - 1];
                    }
                    result += pointer[i][j] ? 1 : 0;
                }
            }
            return result;
        }

        private int get(int x) {
            int result = 0;
            while (x != 0) {
                result += x % 10;
                x /= 10;
            }
            return result;
        }
    }

四、总结:

加油,共勉