题目
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
a|b|c|e
s| f|c|s
a|d|e|e
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路
遍历整个数组,找到开头,然后对这个开头进行匹配查找,
对当前已经匹配了的点,需要查看其四个方向,哪个方向 既没有走过,而且匹配下一个字符,有过有就向这个方向前进一步,如果都没有就后退一步,让之前的点继续四个方向中剩下的方向进行判断,
这个是一个递归过程
return条件为
- 匹配完成了,这是表示匹配成功,返回成功
- 四个方向 都匹配失败了,表示这个点不通,返回失败,只要有一个成功,返回成功
递归入口
每个方向上,如果这个方向没走过、在矩阵内、和要匹配的下个字符相等,就将这个方向的点作为起点进行下一次递归
匹配完成了
class Solution {
public:
int strlen = 0;//被匹配的字符串长度
char* path;//临时储存途经的路径
int rows, cols;//行列长度
//martix 源数组(二维),str 模式串, beginr、beginc 当前所在row、col,e 当前这步所对应str中的下标
bool have(char* matrix, char* str, int beginr, int beginc,int e)//递归式
{
//printf("e=%d %2d %2d\n", e, beginr, beginc);
path[beginr * cols + beginc] = e+1;//标记这步为走过。可以标记为1等常数,e+1
bool is1 = false;//记录向上走是否成狗
bool is2 = false;//右
bool is3 = false;//下
bool is4 = false;//左
if (e + 1 == strlen)//如果str匹配完毕,返回成功
{
return true;
}
if (beginr > 0 && path[beginr * cols - cols + beginc] == 0 && str[e + 1] == matrix[beginr * cols - cols + beginc])//如果能够向上走
{
is1 = have(matrix, str, beginr - 1, beginc, e + 1);//记录向上是否成功
}
if (beginc < cols - 1 && path[beginr * cols + beginc + 1] == 0 && str[e + 1] == matrix[beginr * cols + beginc + 1])//右
{
is2 = have(matrix, str, beginr , beginc + 1, e + 1);
}
if (beginr < rows - 1 && path[beginr * cols + cols + beginc] == 0 && str[e + 1] == matrix[beginr * cols + cols + beginc])//下
{
is3 = have(matrix, str, beginr+1, beginc, e + 1);
}
if (beginc > 0 && path[beginr * cols + beginc - 1] == 0 && str[e + 1] == matrix[beginr * cols + beginc - 1])//左
{
is4 = have(matrix, str, beginr, beginc - 1, e + 1);
}
path[beginr * cols + beginc] = 0;//无论成功失败,这个递归完毕了表示这个点四个方向都走完了,可以交给上一个递归式继续下一个点了,但是这个点可能会在将来被途经到,所有要归零,表示其没走过
return is4 || is3 || is2 || is1;//四个方向只要有一个成功,那就是成功了
}
bool hasPath(char* matrix, int rows, int cols, char* str)//入口
{
path = (char*)malloc(sizeof(char) * rows * cols);//新建一个临时储存流经数组
this->rows = rows;
this->cols = cols;
this->strlen = std::strlen(str);
//遍历所有点
for (int i1 = 0; i1 < rows; i1++)
{
for (int i2 = 0; i2 < cols; i2++)
{
if (matrix[i1 * cols + i2] == str[0])//如果有一个点和模式串开头匹配,就对其递归,看看这个点能不能成功
{
memset(path, 0, sizeof(char) * rows * cols);//每次递归开始前,清空路径
if (have(matrix, str, i1, i2,0))
{
return true;
}
}
}
}
free(path);
return false;
}
};