剑指 Offer 13. 机器人的运动范围
题目描述
地上有一个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
思路
根据题目描述的 m行n列的方格 那么就意味着 在平面直角坐标系中 m 代表y轴坐标长度 n 代表x轴坐标长度
对于坐标 (i,j):
向左走一格: (i, j-1)
向右走一格:(i, j+1)
向上走一格:(i-1, j)
向下走一格:(i+1 ,j)
题目中还有一个要求:
也不能进入行坐标和列坐标的数位之和大于k的格子。
那么需要定义一个函数计算数位的数字之和 同时也注意到提示中n m的范围都在 100 之内 那就好办了 直接通过一次取模运算 和 一次除运算即可
let getSum = function (x){
//获得个位数的值
let g = x % 10;
//获得十位数的值
let s = ~~(x / 10);
return (g + s);
}
还有最重要的部分:记录能走的格子,计算能走多少个格子
- 定义 flag 数组记录能走的格子坐标 能走即赋值为true
- 使用 filter方法 获取 flag数组元素为true的个数 即 机器人能到达的格子数
代码
/**
* @param {number} m
* @param {number} n
* @param {number} k
* @return {number}
*/
var movingCount = function(m, n, k) {
let getSum = function (x){
let g = x % 10;
let s = ~~(x / 10);
return (g + s);
}
let flag = [];
function isAvailable(i, j, m, n, k, flag){
//不可走的情况
if(i < 0 || j < 0 || i > m - 1 || j > n - 1 || (getSum(i) + getSum(j)) > k || flag[i * m + j] === true ){
return;
}
//可走的情况
flag[i * m + j] = true;
// 向左走
isAvailable(i, j - 1, m, n, k, flag);
// 向右走
isAvailable(i, j + 1, m, n, k, flag);
// 向上走
isAvailable(i - 1, j, m, n, k, flag);
// 向下走
isAvailable(i + 1, j, m, n, k, flag);
}
isAvailable(0, 0, m, n, k, flag);
//得到长度
return flag.filter(item=>item === true).length;
};
flag [im+j] 只是为了让 机器人走过的坐标具有唯一的映射 也可以设置为 flag[jn+i] 等