1.DFS
1.首先将机器人放到第一格位置,从第一格判断结束后分别对周围所有格子在进行判断。同时为了防止格子被重复判断,要新建立一个bool类数组来标记格子是否走过。
2.为了使代码的逻辑性更强,我们把这个过程分成三部,用三个函数来实现,①从起点开始,往下递归,②判断其是否越界以及格子是否被走过,③将格子所在的行列的数字拆分后求和与题中的threshold对比
注意:
这里不需要将标记走过的bool数组还原,因为这个题是记录走过的格子数。如果还原了,在其他路径上走过这个格子的话就重复计算了。详情对比题目见矩阵路径
矩阵路径的这个题目需要还原数组。因为不同路径可以走到相同的位置。只要不是所有位置都相同,这个两条不通的路径,矩阵路径的题干如下:
这里不在介绍这道题,思路相同。
C++代码
class Solution {
public:
int movingCount(int m, int n, int k) {
if(k==0){
return 1;
}
vector<vector<bool>>flag(m,vector<bool>(n,true));
int ret=0;
dfs(0,0,m,n,flag,k,ret);
return ret;
}
private:
vector<vector<int>>dirct={{0,1},{1,0},{0,-1},{-1,0}};
void dfs(int row,int col,int ROW,int COL,vector<vector<bool>>&flag,int sum,int&ret){
if(Iegal(row,col,ROW,COL,sum,flag)){
flag[row][col]=false;
ret++;
for(int i=0;i<4;i++){
dfs(row+dirct[i][0],col+dirct[i][1],ROW,COL,flag,sum,ret);
}
}
}
bool Iegal(int row,int col,int ROW,int COL,int k,vector<vector<bool>>&flag){
return (row>=0&&row<ROW)&&(col>=0&&col<COL)&&(sum(row)+sum(col)<=k)&&(flag[row][col]==true);
}
int sum(int num){
int ret=0;
while(num){
ret+=num%10;
num=num/10;
}
return ret;
}
};
时间复杂度 O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN) 。
空间复杂度 O(MN)
2.BFS
BFS/DFS的区别: 两者目标都是遍历整个矩阵,不同点在于搜索顺序不同。DFS 是朝一个方向走到底,再回退,以此类推;BFS 则是按照类似“平推”的方式向前一层一层的搜索。
实现BFS通常需要使用队列。
- 队列头部数据出队列,判断是不是符合题干。
- bool数组标记这个位置已经走过
- 将这个位置周围没有被bool数字标记的其他方向的合法格子入队。并且将这个格子周围的格子使用bool数组标记。
- 当队列的大小为0时跳出循环。
在这个过程中每一次入队都代表机器人可以跳过这个格子,所以入队次数就算最后的答案。
C++代码
class Solution {
vector<vector<int>>dirct={{0,1},{1,0},{0,-1},{-1,0}};
public:
int movingCount(int m, int n, int k) {
if(k==0){
return 1;
}
queue<vector<int>>q;
vector<vector<bool>>flag(m,vector<bool>(n,true));
int ret=1;
q.push({0,0});
flag[0][0]=false;
while(!q.empty()){
vector<int>pos=q.front();
q.pop();
for(int i=0;i<4;i++){
int nextrow=pos[0]+dirct[i][0];
int nextcol=pos[1]+dirct[i][1];
if(Iegal(nextrow,nextcol,m,n,k,flag)){
flag[nextrow][nextcol]=false;
q.push({nextrow,nextcol});
ret++;
}
}
}
return ret;
}
private:
bool Iegal(int row,int col,int ROW,int COL,int k,vector<vector<bool>>&flag){
return (row>=0&&row<ROW)&&(col>=0&&col<COL)&&(sum(row)+sum(col)<=k)&&(flag[row][col]==true);
}
int sum(int num){
int ret=0;
while(num>0){
ret+=num%10;
num/=10;
}
return ret;
}
};
时间复杂度O(MN)
空间复杂度O(MN)
3.递推迭代
根据上面的层序遍历代码分析可知。
设机器人的位置在[i,j]那么他一定是从[i-1,j]或者[i,j-1]移动来的,所以机器人每次的移动可以优化向左或向下移动。
标记数组定义为vector<vector< int>>其中0代表不可达,1代表可达。
最后的答案就算标记数组元素和。
C++代码
class Solution {
public:
int movingCount(int m, int n, int k) {
if(k==0){
return 1;
}
vector<vector<int>>flag(m,vector<int>(n,0));
flag[0][0]=1;
int ret=1;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if((i==0&&j==0)||(sum(i)+sum(j)>k)){
continue;
}
else{
if(i-1>=0){
flag[i][j]|=flag[i-1][j];
}
if(j-1>=0){
flag[i][j]|=flag[i][j-1];
}
ret+=flag[i][j];
}
}
}
return ret;
}
private:
int sum(int num){
int ret=0;
while(num>0){
ret+=num%10;
num/=10;
}
return ret;
}
};
时间复杂度 O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O(MN) 。
空间复杂度 O(MN)