12 矩阵中的路径
题目描述:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。
例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子
a b c e
s f c s
a d e e
测试用例:
1)功能测试(在多行多列矩阵中存在或者不存在路径)
2)边界值测试(矩阵中只有一行或者只有一列;矩阵中所有字母都是相同的)
3)特殊输入测试(输入nullptr指针)
解题思路:
1)使用回溯算法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | class Solution { public : bool hasPath( char * matrix, int rows, int cols, char * str) { if (matrix== nullptr || rows<1 || cols<1 || str== nullptr ) //是||而不是&& return false ; //定义标记矩阵 //bool visited[] = new[rows*cols];//error:expected a type bool * visited = new bool [rows*cols]; memset (visited,0,rows*cols); //将每个元素初始化为0(false) //定义路径的第几个字符 int pathLocate = 0; //遍历矩阵,寻找起始节点的位置 for ( int row=0; row<rows; ++row){ for ( int col=0; col<cols; ++col){ if (hasPathCore(matrix,rows,cols,str,row,col,pathLocate,visited)) return true ; } } delete [] visited; return false ; } bool hasPathCore( const char * matrix, int rows, int cols, const char * str, int row, int col, int & pathLocate, bool * visited){ //pathLocate一定要取引用 //终止条件: 到达字符串尾,说明前面所有的字符都找到了,即矩阵中含有字符串 if (str[pathLocate]== '\0' ) return true ; bool hasPath = false ; if (row>=0 && row<rows && col>=0 && col<cols && //索引在矩阵范围内 是row>=0,而不是row>0 str[pathLocate]==matrix[row*cols+col] && //在矩阵当前位置,找到第pathLocate个字符 //error:[row*rows+col] visited[row*cols+col]== false ){ //该位置没有在路径中 visited[row*cols+col]==false 或!visited[row*cols+col] ++pathLocate; //寻找下一个节点 //不能放在外面(永远不会进入if):因为if中判断visited[row*cols+col]==false visited[row*cols+col]= true ; //当前节点被占用 hasPath = hasPathCore(matrix,rows,cols,str,row,col-1,pathLocate,visited) //左 || hasPathCore(matrix,rows,cols,str,row-1,col,pathLocate,visited) //上 || hasPathCore(matrix,rows,cols,str,row,col+1,pathLocate,visited) //右 || hasPathCore(matrix,rows,cols,str,row+1,col,pathLocate,visited); //下 if (!hasPath){ --pathLocate; visited[row*cols+col]= false ; } } return hasPath; } }; |
2)标准的DFS搜索,同回溯算法一样思路,只是矩阵用二维数组表示。有空间浪费
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | //思路:扫一遍矩阵 如果矩阵当前字符等于要查找的第一个字符,则从这个点dfs class Solution { public : void build( char * matrix, int rows, int cols) //建立二维的矩阵 { int cnt=0; for ( int i=0;i<rows;++i) for ( int j=0;j<cols;++j) maze[i][j]=matrix[cnt++]; } //(x,y)表示当前坐标,des表示要查找的字符串,cnt表示已经匹配上了多少个 //len表示要查找的字符串的长度(好确定递归出口) bool dfs( int x, int y, char *des, int cnt, int len, int rows, int cols) { if (cnt>=len) //出口 return true ; vis[x][y]=1; for ( int i=0;i<=3;++i) { int newx=x+dx[i],newy=y+dy[i]; //四个方向:上下左右 if (vis[newx][newy]==0 && newx>=0 && newx<rows && newy>=0 && newy<cols && maze[newx][newy]==des[cnt]) { if (dfs(newx,newy,des,cnt+1,len,rows,cols)) return true ; } } return false ; //匹配失败 } bool hasPath( char * matrix, int rows, int cols, char * str) { build(matrix,rows,cols); memset (vis,0, sizeof (vis)); for ( int i=0;i<rows;++i) //遍历一遍,所以要记得重置vis数组 { for ( int j=0;j<cols;++j) { if (maze[i][j]==str[0]&&dfs(i,j,str,1, strlen (str),rows,cols)) return true ; //重新选择起点寻找路径 所以vis要重新记录 memset (vis,0, sizeof (vis)); //重置 } } return false ; } private : //矩阵尺寸固定为100*100,会造成空间浪费 char maze[100][100]; //题目给的是char* matrix转换为二维char**maze int vis[100][100]; //记录是否被访问过 //int dx[]={0,1,0,-1},dy[]={1,0,-1,0}; //错误:无法从类内初始值设定项推断数组绑定, 要指定元素个数。 int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0}; //四个方向 }; |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步