请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
思路在书上和代码里面注释的很清楚
代码:
class Solution {
public:
bool hasPath(const char *matrix, int rows, int cols, const char* str)
{
if (matrix == nullptr || rows <= 0 || cols <= 0 || str == nullptr)
return false;
bool *visited = new bool[rows*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;
}
//hasPathCore(初始矩阵,矩阵行数,矩阵列数,行索引,列索引,待查询字符串,查找的路径长度,访问标志矩阵)
bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int pathLength, bool* visited)
{
//当访问到str字符串最后的结束符‘\0’时结束回溯,返回true;
if (str[pathLength] == '\0')
return true;
bool hasPath = false;
//满足要求继续查找下一个字符:坐标在边界之内,str字符串中的字符出现在了初始矩阵里,改点未被访问过。
if (row >= 0 && row < rows && col >= 0 && col < cols
&& matrix[row * cols + col] == str[pathLength]
&& !visited[row * cols + col])
{
//满足要求表示这点已经被访问了,路径长度加1,指向下一个字符,访问标志置为true;
++pathLength;
visited[row * cols + col] = true;
//调用自身从当前点开始检测四周是否有符合要求的点
hasPath = hasPathCore(matrix, rows, cols, row, col - 1, str, pathLength, visited)
|| 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+1, col, str, pathLength, visited);
/*
若有符合要求的字符串,则此次代码会在if (str[pathLength == '\0']) return true;中结束,并且返回true回到主程序
若路径途中没有符合要求的字符串,则会回溯到上一步pathLength--中重新找下一个字符。
*/
if (!hasPath)
{
--pathLength;
visited[row * cols + col] = false;
}
}
return hasPath;
}
};更新代码及讲解
DFS具体讲解参考:https://blog.csdn.net/raphealguo/article/details/7560918
bool hasPath(const char* matrix, int rows, int cols, const char* str)
{
if (matrix == nullptr || str == nullptr || rows <= 0 || cols <= 0)
return false;
//定义访问矩阵
vector<vector<bool> >visit(rows, vector<bool>(cols, false));
//记录遍历长度,遍历到str最后一位时,说明找到我们需要的字符串了
int pathLength = 0;
//按照数组从第一位开始遍历回溯
for (int row=0; row < rows; ++row)
{
for (int col=0; col < cols; ++col)
{
//进入DFS判断(row,col)是否是解的一个点
if (DFS(matrix, rows, cols, str, row, col, visit, pathLength))
return true;
//程序运行到这,表示从(row,col)出发找不到解,所以换一个节点开始
}
}
return false;
}
bool DFS(const char* matrix, int rows, int cols, const char* str, int row, int col, vector<vector<bool> >& visit, int& pathLength)
{
//回溯终止标志:若遍历到str结尾返回true;
if (str[pathLength] == '\0')
return true;
//当(row,col)是其中一位字符且没有被访问过,则可以从这位开始遍历回溯
if (row >= 0 && row < rows && col >= 0 && col < cols && matrix[row * cols + col] == str[pathLength] && visit[row][col] == false)
{
//长度加1,访问位置true
++pathLength;
visit[row][col] = true;
/*
这一位遍历完后,接着按照四个方向找下一位合适的字符,
若由此点开始有满足要求的字符出现,则在这会返回true
*/
if (DFS(matrix, rows, cols, str, row - 1, col, visit, pathLength) ||
DFS(matrix, rows, cols, str, row, col + 1, visit, pathLength) ||
DFS(matrix, rows, cols, str, row + 1, col, visit, pathLength) ||
DFS(matrix, rows, cols, str, row, col - 1, visit, pathLength))
return true;
/*
程序运行到这,表示这一位字符沿四个方向运行下去都没有找到合适的节点序列,所以必须从此点回溯。
回溯之前将其重新设置成未访问,因为它有可能出现在下一次搜索的别的路径中
*/
--pathLength;
visit[row][col] = false;
}
//到这里,针对(row,col)这一个点的遍历就结束了,返回true表示本次搜索没有找到解,主程序还得从下一个点入手找解
return false;
}

京公网安备 11010502036488号