美文网首页
面试题13:机器人的运动范围

面试题13:机器人的运动范围

作者: 潘雪雯 | 来源:发表于2020-05-12 08:23 被阅读0次

    题目

    地上有一个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。
    例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7=18。但它不能进入方格(35,38),因为3+5+3+8=19.请问该机器人能够到达多少个格子?

    解题思路

    1. 明白题目含义:行坐标和列坐标的数位之和大于k的格子,即这道题是针对矩阵坐标而非矩阵中的值。
    2. 采用回溯法解决。
    • 机器人有回退行为
      如果k=1,机器人能到达的格子为(0,0)-->(0,1)和(0,0)-->(1,0)两种方式。也就是说当机器人走到(0,1)时可以回退到(0,0)再继续找到(1,0)。
      当行和列为5,k = 3时经过的格子图(用以理解下面的递归代码)


      image.png
    • 机器人无回退行为
      同上,只能找到一条路径能到达的格子为(0,0)-->(0,1)或(0,0)-->(1,0)

    代码

    • 一维数组存储二维数据(有回退行为的)
      每到达一个格子,就判断该格子的上下左右的格子是否满足条件。把每个方向能到达的格子数a[i]记录下来并相加
    class Solution{
      public:
        int add_row_col(int loc)
        {
            int tt = 0;
            while(loc>0)
            {
                tt += loc%10;
                loc /= 10;
            }
            return tt;
        }
        
        int movingCountCore(int threshold,int row,int col,int rows,int cols,int *visited)
        {
            int a[4];
            int result = 0;
            memset(a,0,4*sizeof(int));
            if(visited[row*cols+col]==0 && add_row_col(row) + add_row_col(col) <= threshold)
            {
                visited[row*cols + col] = 1;
                
                //向上找
                if(row>0 )
                {
                    a[0] = movingCountCore(threshold,row-1,col,rows,cols,visited);
                }
                //下
                if(row < rows-1 )
                {
                    a[1] = movingCountCore(threshold,row+1,col,rows,cols,visited);
                }
    
                //左
    
                if(col > 0)
                {
                    a[2] = movingCountCore(threshold,row,col-1,rows,cols,visited);
                }
                //右
    
                if(col < cols-1)
                {
                    a[3] = movingCountCore(threshold,row,col+1,rows,cols,visited);
                }
                
                result = 1+a[0]+a[1]+a[2]+a[3];
                //cout << "result: " << result << endl;
            }
            else
            {
                result = 0;
            }
    
            cout << "result: " << result << endl;
            return result;
        }
    
        int movingCount(int threshold,int rows,int cols)
        {
            if(threshold < 0 || rows <= 0 || cols <= 0 )
            {
                return 0;
            }
            int visited[rows*cols]; //标识路径是否已进入每个格子
            memset(visited,0,sizeof(int)*rows*cols);
            return movingCountCore(threshold,0,0,rows,cols,visited);
        }
    };
    
    • 二维数组存储二维数据(有回退行为的)
    • 细节
      定义全局变量
    #define rows 4
    #define cols 4
    #define threshold 2
    
    class Solution{
      public:
        int add_row_col(int loc)
        {
            int tt = 0;
            while(loc>0)
            {
                tt += loc%10;
                loc /= 10;
            }
            return tt;
        }
        
        int movingCountCore(int row,int col,int visited[][cols])
        {
            int a[4];
            int result = 0;
            memset(a,0,4*sizeof(int));
            if(visited[row][col]==0 && add_row_col(row) + add_row_col(col) <= threshold)
            {
                visited[row][col] = 1;
                
                //向上找
                if(row>0 )
                {
                    a[0] = movingCountCore(row-1,col,visited);
                }
                //下
                if(row < rows-1 )
                {
                    a[1] = movingCountCore(row+1,col,visited);
                }
    
                //左
    
                if(col > 0)
                {
                    a[2] = movingCountCore(row,col-1,visited);
                }
                //右
    
                if(col < cols-1)
                {
                    a[3] = movingCountCore(row,col+1,visited);
                }
                
                result = 1+a[0]+a[1]+a[2]+a[3];
                //cout << "result: " << result << endl;
            }
            else
            {
                result = 0;
            }
    
            cout << "result: " << result << endl;
            return result;
        }
    
        int movingCount()
        {
            if(threshold < 0 || rows <= 0 || cols <= 0 )
            {
                return 0;
            }
            int visited[rows][cols]; //标识路径是否已进入每个格子
            memset(visited,0,sizeof(int)*rows*cols);
            return movingCountCore(0,0,visited);
        }
    };
    
    • 一维数组存储二维数据(无回退行为的)
      找到每个格子上下左右能到达的格子数a[i],然后比较哪个方向的格子数最多,就把result= max(a[0],a[1],a[2],a[3]).
    class Solution{
      public:
        int add_row_col(int loc)
        {
            int tt = 0;
            while(loc>0)
            {
                tt += loc%10;
                loc /= 10;
            }
            return tt;
        }
        
        int movingCountCore(int threshold,int row,int col,int rows,int cols,int *visited)
        {
            int a[4];
            int result = 0;
            memset(a,0,4*sizeof(int));
            if(visited[row*cols+col]==0 && add_row_col(row) + add_row_col(col) <= threshold)
            {
                visited[row*cols + col] = 1;
                
                //向上找
                if(row>0 )
                {
                    a[0] = movingCountCore(threshold,row-1,col,rows,cols,visited);
                }
                //下
                if(row < rows-1 )
                {
                    a[1] = movingCountCore(threshold,row+1,col,rows,cols,visited);
                }
    
                //左
    
                if(col > 0)
                {
                    a[2] = movingCountCore(threshold,row,col-1,rows,cols,visited);
                }
                //右
    
                if(col < cols-1)
                {
                    a[3] = movingCountCore(threshold,row,col+1,rows,cols,visited);
                }
                
                //result = 1+a[0]+a[1]+a[2]+a[3];
                //无回退行为
                for(int i=0;i<4;i++)
                {
                    if(result < a[i])
                    {
                        result = a[i];
                    }
                }
                result +=1;
                //cout << "result: " << result << endl;
            }
            else
            {
                result = 0;
            }
    
            cout << "result: " << result << endl;
            return result;
        }
    
        int movingCount(int threshold,int rows,int cols)
        {
            if(threshold < 0 || rows <= 0 || cols <= 0 )
            {
                return 0;
            }
            int visited[rows*cols]; //标识路径是否已进入每个格子
            memset(visited,0,sizeof(int)*rows*cols);
            return movingCountCore(threshold,0,0,rows,cols,visited);
        }
    };
    

    总结

    建议使用一维数组的方式,这样的时间复杂度更低,效率更高。当机器人无回退行为时,和面试题47:礼物的最大价值就是同一个类型的。

    完整代码见Github

    相关文章

      网友评论

          本文标题:面试题13:机器人的运动范围

          本文链接:https://www.haomeiwen.com/subject/yktunhtx.html