题目描述
地上有一个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。请问该机器人能够到达多少个格子?
解题思路
第一眼看到想用迭代,然后失败了(主要是理解题意有问题),再次尝试用递归,然后超时,最后还是选择迭代,在迭代时主要涉及到两个点:
- 当前位置的坐标和必须满足条件,即所有位的和<k。
- 当前位置必须有相邻的点为能够到达的点。
我选择的办法是用了一个标记数组,将[0,0]点标记为true,然后对数组进行一次遍历,如果当前点为true,则判断该点的右边和下边的相邻点是否满足条件,如果满足,则将其标记为true,最后统计数组中为true的点的数目即可。
代码
递归代码(超时无法通过):
class Solution {
public int movingCount(int m, int n, int k) {
int res=0;
boolean[][] state=new boolean[m][n];
res=get_numbers(state,0,0,k);
return res;
}
public int get_numbers(boolean[][] state,int m,int n,int k){
if((m%10+m/10+n%10+n/10)>k||m>=state.length||n>=state[0].length){
return 0;
}
int res=0;
if(!state[m][n]){
state[m][n]=true;
res++;
}
return get_numbers(state,m+1,n,k)+get_numbers(state,m,n+1,k)+res;
}
}
我在思考一个问题:递归中如果加限制条件是否可以完成该题目?(暂时没解决)
迭代代码:
class Solution {
public int movingCount(int m, int n, int k) {
int res=0;
boolean[][] state=new boolean[m][n];
state[0][0]=true;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(state[i][j]){
if(i<m-1){
if(get_number(i+1,j)<=k){
state[i+1][j]=true;
}
}
if(j<n-1){
if(get_number(i,j+1)<=k){
state[i][j+1]=true;
}
}
}
}
}
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(state[i][j]){
res++;
}
}
}
return res;
}
public int get_number(int m,int n){
int sum=0;
if(m==100){
sum=sum+1;
}else{
sum=sum+m/10+m%10;
}
if(n==100){
sum=sum+1;
}else{
sum=sum+n/10+n%10;
}
return sum;
}
}
这是官方解法中的一种,还有一种解法是广度优先,通过一次循环遍历计算到达每个点时在该点所能到达的格子数,而每个点的格子数为其上方和左方的格子数之和,这两种方法大同小异,时间复杂度和空间复杂度也没区别,细细想想即可完成,可以尝试一下。