机器人的运动范围 | 算法

118 阅读2分钟

面试题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;
};