面试题六---矩阵中的路径详解

1.题目

请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的3乘4的矩阵中包含了一条字符串“bfce”的路径(路径中的字母用粗体标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
a b t g
c f c s
j d e h

2.笔者解答

第一反应是递归,和一个标记路径的数组,其它的貌似也没什么了,直接上代码。

int dr[4]={1,-1,0,0};
int dc[4]={0,0,1,-1};//方向向量
int road[m][n];
//m为二维矩阵的高,n为二维矩阵的宽,double_string[m][n]为原二维矩阵
int i,j;
for(i=0;i<m;i++)
 for(j=0;j<n;j++)
    road[i][j]=0;//将路径数组初始标记为未走过,走过后,赋值为1
bool get_string(int depth,int aidstring_length,char *aidstring,int x,int y)
{
    int i;
    if(double_string[x][y].equals(aidstring[depth])
    {
         road[x][y]=1;
        if(depth==length)
          return true;
    }
    for(i=0;i<4;i++)
    {
      if(x+dr[i]>=0&&x+dr[i]<m&&y+dc[i]>=0&&y+dc[i]<n)
      {  
        if(road[x+dr[i]][y+dc[i]]==0)    
        {
         if(get_string(depth++,adistring_length,aidstring,x+dr[i],y+dc[i]))
            return true;
        }
      }
    }
}

3.就题论题

这是一个可以用回溯法解决的典型题。首先,在矩阵中任选中一个格子作为路径的起点。假设矩阵矩阵中某个格子的字符为ch,并且这个格子将对应于路径上的第i个字符不是ch,那么将这个格子不可能处在路径上的第i个位置。如果路径上的第i个字符正好是ch,那么到相邻的格子寻找路径上的第i+1个字符。除矩阵边界上的格子之外,其他格子都有四个相邻的格子。重复这个过程,直到路径上的所有字符都在矩阵中找到相应的位置。
由于回溯法的递归特性,路径可以被看成一个栈。当在矩阵中定位了路径中前n个字符的位置之后,在与第n个字符对应的格子的周围都没有找到第n+1个字符,这时候只好在路径上回到第n-1个字符,重新定位第n个字符。
由于路径不能重复进入矩阵的格子,所以还需要定义和字符矩阵大小一样的布尔值矩阵,用来标识路径是否已经进入了每个格子。下面的代码实现了这个回溯算法:

   bool hasPath(char* matrix,int rows,int cols,char* str)
   {
      if(matrix==nullptr||rows<1||cols<1||str==nullptr)
         return false;
      bool *visited=new bool[row*cols];
      memset(visited,0,rows*cols);
      int pathLength=0;
      for(int row=0;row<rows;++row)
      {
        for(int col=0;col<cols;++col)
        {
          if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visited))
          {
            return true;
          }
        }
      }
      delete[] visited;
      return false;
   }
bool haspathCore(const char* matrix,int rows,int cols,int row,int col,const char* str,int & pathLength,bool* visited)
{
  if(str[pathLength]=='\0')
    return true;
  bool hasPath==false;
  if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row*cols+col]==str[pathLength]&&!visited[row*cols+col])
  {
   ++pathLength;
   visited[row*cols+col]=true;
   hasPath=hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited)
   ||hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited)
   ||hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited)
   ||hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited)
     if(!hasPath)
  {
    --pathLength;
    visited[row*cols+col]=false;
  }
  }
 return hasPath;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赶路的苟狗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值