面试题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
解题思路:使用典型的dfs算法。
javascript:
var movingCount = function(m, n, k) {
var count = 0, //计数
obj = []; //用来存放已经走过的格子
var dfs = (i, j) => {
if (i < 0 || i >= m || j < 0 || j >= n || sum(i, j) > k) return false;//边界条件
var target = JSON.stringify([i, j]);
if (!obj[target]) { //如果是没走过的格子,计数+1,且存到对象里
obj[target] = true;
count++;
} else { //如果是走过的格子,返回当前计数值
return count;
}
dfs(i + 1, j);
dfs(i, j + 1);
dfs(i - 1, j);
dfs(i, j - 1);
};
function sum(i, j) { //用来求数字之和的函数
var arr1 = i.toString().split('');
//array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
//function:必需。用于执行每个数组元素的函数。initialValue:可选。传递给函数的初始值
var num1 = arr1.reduce((pre, cur) => {return pre + cur * 1}, 0);
var arr2 = j.toString().split('');
var num2 = arr2.reduce((pre, cur) => {return pre + cur * 1}, 0);
return num1 + num2;
};
//从初始位置开始调用
dfs(0, 0);
return count;
};
typescript:
function movingCount(m: number, n: number, k: number): number {
//求位数和
const getSum = x => x % 10 + Math.floor(x / 10);
const moved = new Map<string, boolean>();
const judge = (i: number, j: number) => {
if (i < 0 || j < 0 || i > m - 1 || j> n - 1 //越界
|| (getSum(i) + getSum(j)) > k //超出限制
|| moved.get(`${i}-${j}`) //已经走过
){
return false;
}
//满足条件就标记为走过
moved.set(`${i}-${j}`, true);
judge(i - 1, j);
judge(i + 1, j);
judge(i, j - 1);
judge(i, j + 1);
};
//从第一个位置开始判断
judge(0,0);
return moved.size;
};