剑指 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
解题思路
这道题求运动范围,依然是矩阵,只是改变了限制条件。这种一般都是使用回溯法来解决(与八皇后问题是一类问题)。
1.确定是否需要返回值:
由于需要计算具体的值,并且有限制条件,不是递归完所有情况,所以需要有返回值。这里求的是个数,因此返回值类型为int。
2.确定边界条件:
这道题结束循环的条件很简单,首先是下标不能越界,否则返回0.
其次是计算坐标的数位之和。如果>k,则返回0.
另外,为了解决重复计数的问题,还需要设置一个数组用于记录当前位置的状态。因此条件中需要加:当前位置如果状态为已进入过,则返回0.
3.单层递归逻辑
首先,进入的第一个位置是确定的,为[0,0]。
另外,从第一个位置开始,要遍历的方向有四个(上下左右)。
由于递归函数返回值是个数(int),因此只需记录下每个方向的返回值,最后四个方向的返回值之和再加上出发位置的1个格子,得到的值即为机器人所能到达的所有格子数。
4.这道题只是判断能否到达,因此不需要记录路径,只需要求和。
其他解法:
看到题解中有大佬使用了并查集(用于计算连通域的面积),但是并查集我还不会,留个坑。
Java解法
class Solution {
public int movingCount(int m, int n, int k) {
int res = 0;
int [][] flag = new int [m][n];
res = helper(m,n,k,0,0,flag);
return res;
}
public int helper(int m,int n,int k,int l,int r,int [][] flag){
if(l==m || r==n || l<0 || r<0 || flag[l][r]==1) return 0;
if(getSum(l,r)>k) return 0;
flag[l][r]=1;
int up = helper(m,n,k,l-1,r,flag);
int down = helper(m,n,k,l+1,r,flag);
int left = helper(m,n,k,l,r-1,flag);
int right = helper(m,n,k,l,r+1,flag);
return up+down+left+right+1;
}
public int getSum(int l,int r){
int res = 0;
res+=(l/100);
res+=(l%100/10);
res+=(l%10);
res+=(r/100);
res+=(r%100/10);
res+=(r%10);
return res;
}
}