题解 | #机器人的运动范围#
机器人的运动范围
http://www.nowcoder.com/practice/6e5207314b5241fb83f2329e89fdecc8
题目:机器人的运动范围
描述:地上有一个rows行和cols列的方格。坐标从[0,0]到[rows-1,cols-1]。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于threshold的格子。 例如,当threshold为18时,机器人能够进入方格[35,37],因为3+5+3+7 = 18。但是,它不能进入方格[35,38],因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
范围: 1 <= rows, cols<= 100,0 <= threshold <= 20
示例1:输入:1,2,3,返回值:3
解法一:
思路分析:我们可以使用递归法进行判断,因为题目中有要求,首先保证机器人不能进入行坐标和列坐标的数位之和大于threshole的格子,如果发现大于,则将值进行返回,从上一次的位置再向其他位置进行递归,同时使用布尔值矩阵去判断是否进入,其次机器人走的格子超出了棋盘的范围,即进入的行列数大于最大的行列数,或者小于0则不符合条件,我们在回退的过程中不需要对标志或者计数进行清除。
实例分析:输入:2,5,5,其中threshole为2,行为5,列为5。
|
| 列/行 | 0 | 1 | 2 | 3 | 4 |
|
| 0 | 满足条件 | 满足条件 | 满足条件 |
|
|
|
| 1 | 满足条件 | 满足条件 |
|
|
|
|
| 2 | 满足条件 |
|
|
|
|
|
| 3 |
|
|
|
|
|
|
| 4 |
|
|
|
|
|
| 在进行运行的同时,其具体判断条件大致有三条:1.数位之和大于给定的阈值2.机器人走的格子超出了棋盘的范围,即进入的行列数大于最大的行列数,或者小于0 3.当前格子已经被访问过了 | ||||||
机器人每到一个位置,判断该位置是否有效,如果有效(满足三个条件),往左右上下移动,重复上述行为,最终遍历的范围就是运动的范围。通过程序运行最终返回结果值为6。
具体C++代码如下所示:
class Solution {
public:
//提取数的每一位的和
int getDigitalSum(int num)
{
int sum = 0;
while(num){
sum += num%10;
num = num/10;
}
return sum;
}
int movingCountCore(int threshold,int rows,int cols,int row,int col,bool *visited){
if((threshold < (getDigitalSum(row)+getDigitalSum(col)))||(row >= rows)||(col >= cols)||(row < 0)||(col < 0)||(visited[row*cols+col]))
return 0;
//满足所有访问条件,说明机器人可以进入该格子。
int resu = 1;
visited[row*cols+col] = true;
//当前格子的四周进行查看
resu = resu + movingCountCore(threshold,rows,cols,row+1,col,visited)
+ movingCountCore(threshold,rows,cols,row,col+1,visited)
+ movingCountCore(threshold,rows,cols,row-1,col,visited)
+ movingCountCore(threshold,rows,cols,row,col-1,visited);
return resu;
}
int movingCount(int threshold, int rows, int cols){
//输入不满足条件时,行列小于等于0的情况,返回0
if((threshold < 0)||(rows <=0)||(cols <= 0))return 0;
//建立一个同样大小的bool矩阵用于记录是否已经判断过
bool *visited = (bool *)malloc(rows*cols);
memset(visited,false,rows*cols);
int resu = 0;
resu = movingCountCore(threshold,rows,cols,0,0,visited);
//记得释放分配的内存空间
free(visited);
return resu;
}
}; 其中时间复杂度为O(MN),MN为矩阵的大小,矩阵中的元素最多访问一次。空间复杂度为O(MN),因为要申请一片连续的内存空间。
解法二:
思路分析:我们使用暴力循环的方法,判断该坐标内的每一个元素是否符合上述三个条件,如果符合条件,就将count++,否则,不予理会,用visited判断记录下一个可以进入的结点。
具体Java代码如下所示:
public class Solution {
public int movingCount(int k, int m, int n) {
int count = 0;//表示次数
boolean[][] visited = new boolean[m][n];//新建visited对象
visited[0][0] = true;//第一个值肯定为真
for(int i =0; i<m; i++){//循环判断
for(int j =0; j<n; j++){
if(compareKey(i, j, k) && visited[i][j]){
if(i+1 < m)
visited[i+1][j] = true;
if(j+1 < n)
visited[i][j+1] = true;
count++;
}
}
}
return count;
}
/**
*判断值是否符合
**/
public boolean compareKey(int i, int j, int k){
int sum = sumNum(i) + sumNum(j);
if(sum > k){
return false;
}
return true;
}
/**
*整数num的各位值之和
**/
public int sumNum(int num){
int sum = 0;
while(num > 0){
sum = sum + num % 10;
num = num / 10;
}
return sum;
}
} 因为要将每行每列都进行判断,所以时间复杂度为O(N^2)。空间复杂度为O(1)。
在解决问题的同时,不断与人交流学习,通过牛客各式各样的题目,学习分享。
联想公司福利 1489人发布
查看6道真题和解析