一、题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子
二、解析
这是我看过一个人的解析思路,我觉得是不错的。
首先分析一下这是一道dfs的题目,我们可以先找到字符串第一个字符在矩阵中有没有匹配,再在他的上下左右去找第二个,同样思路去找第三个直到字符串匹配完。
这里就要用到递归了,递归函数就是当前处理的问题是什么,并且下一次在规模减小的情况下处理相同的问题。比如此题:当前处理的问题是:判断字符串str[0 ... len]是否在mat中匹配,显然下一次递归处理的问题是:如果str[0]已经匹配,则判断字符串str[1 ... len]是否在mat中匹配。
递归函数要怎么写呢?
dfs(){
// 第一步,检查下标是否满足条件
// 第二步:检查是否被访问过,或者是否满足当前匹配条件
// 第三步:检查是否匹配当前字符串的字符
// 第四步:上面没有返回,说明当前矩阵的字符匹配字符串要匹配的字符,对其做标记,然后匹配下一个
// 第五步:上下左右匹配下个字符,使用循环
dfs(下一次)
// 第六步:如果上下左右都没有匹配,将此时已经标记的矩阵字符修改回去(回溯)
}
思考dfs参数,因为一次递归是要匹配一个字符,所以要确定矩阵的某个字符,以及字符串的某个字符,矩阵靠行列确定,字符串靠具体到那一个字符确定,也就是说要给一个整数表示当前匹配到哪个字符
//i,j表示矩阵位置,pos表示匹配字符串第几个,一次dfs匹配一个字符
bool dfs(int i,int j,int pos,char * str)
三、代码实现
class Solution {
public:
int h;//表示行数
int w;//表示列数
char * mar;//矩阵
int str_len;//字符串长度
int d[5]={-1,0,1,0,-1};//上下左右移动时用到
bool hasPath(char* matrix, int rows, int cols, char* str)
{
h=rows;
w=cols;
mar=matrix;
str_len=strlen(str);
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
//循环匹配第一个字符
if(dfs(i,j,0,str))
return true;
}
}
return false;
}
//i,j表示矩阵位置,pos表示匹配字符串第几个,一次dfs匹配一个字符
bool dfs(int i,int j,int pos,char * str){
//超出边界
if(i<0||i>=h||j<0||j>=w)
return false;
char ch = mar[i*w+j];
//#为已经标记了,已经标记或不等于返回false
if(ch=='#'||ch!=str[pos])
return false;
//字符串全部匹配完
if(pos+1==str_len)
return true;
//当前字符匹配成功进行标记
mar[i*w+j]='#';
//上下左右移动匹配下个字符
for(int l=0;l<4;l++){
if(dfs(i+d[l],j+d[l+1],pos+1,str))
return true;
}
//上下左右匹配下个字符不成功,将矩形的#标记重新改回原来的字符
mar[i*w+j]=ch;
return false;
}
};