题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路:
回溯算法:首先,在矩阵中任选一个格子作为路径的起点,设此格子中的字符为ch,如果路径上的第1个字符不是ch,那么这个格子不可能是路径的起点,如果路径上的第一个字符是ch,那么,接着分别判断这个格子的上下左右四个格子中的字符是否是路径上的第2个字符,(除在矩阵边界上的格子之外,其他格子都有4个相邻的格子),重复这个过程,依次找到路径上的所有字符。如果最终没找到,则返回false。
由于回溯法的递归特性,当在矩阵中定位了路径中前n个字符的位置之后,在与第n个字符对应的格子的周围都没有找到第n+1个字符,这个时候要在路径上回到第n-1个字符,重新定位第n个字符。
由于路径不能重复进入矩阵的格子,所以需要定义和字符矩阵大小相同的布尔值矩阵,用来标识路径是否已经进入到每个格子。
当矩阵中坐标为 (i, j) 的格子和路径字符串中相应的字符相同时,从4个相邻的格子 (i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1)去定位路径字符串中的下一个字符。如果4个相邻的格子都没有匹配字符串中的下一个的字符,表明当前路径字符串在矩阵中的定位不正确,需要回到前一个重新定位。依此重复,直到找到路径中所有字符。
#include<iostream>
#include<string>
using namespace std;
class Solution {
public:
bool hasPath(char* matrix, int rows, int cols, char* str)
{
if (matrix == NULL || rows < 1 || cols < 1 || str == NULL)
return false;
bool* visited = new bool[rows*cols]; //定义一个辅助矩阵,用来标记路径是否已经进入了每个格子
memset(visited, 0, rows*cols);////将visited所指向的某一块内存中的后rows*cols个字节的内容全部设置为0指定的ASCII值
int pathIndex = 0;
for (int i = 0; i < rows; ++i) //该循环是为了实现从任何一个位置出发,寻找路径
{
for (int j = 0; j < cols; ++j)
{
if (hasPathCore(matrix, rows, cols, i, j, str, pathIndex, visited))
return true;
}
}
delete[] visited;
return false;
}
/*此函数用来判断在当前路径满足条件下,相邻格子中是否存在一个格子满足条件*/
bool hasPathCore(char* matrix, int rows, int cols, int i, int j, char* str, int& pathIndex, bool* visited)
{
if (str[pathIndex] == '\0')
return true;
bool res = false;
if (i >= 0 && i < rows && j >= 0 && j < cols && matrix[i*cols + j] == str[pathIndex] && !visited[i*cols + j])
{
++pathIndex;
visited[i*cols + j] = true;
/*如果矩阵格子(row,col)与路径字符串中下标为pathIndex的字符一样时,
从它的4个相邻格子中寻找与路径字符串下标为pathIndex+1的字符相等的格子*/
res = hasPathCore(matrix, rows, cols, i, j - 1, str, pathIndex, visited) ||
hasPathCore(matrix, rows, cols, i - 1, j, str, pathIndex, visited) ||
hasPathCore(matrix, rows, cols, i, j + 1, str, pathIndex, visited) ||
hasPathCore(matrix, rows, cols, i + 1, j, str, pathIndex, visited);
if (!res)
{
--pathIndex; //如果没找到,则说明当前第pathIndex个字符定位不正确,返回上一个位置重新定位
visited[i*cols + j] = false;
}
}
return res;
}
};
int main()
{
char matrix[] = "abcesfcsadee";
char str[] = "abcb";
int rows = 3, cols = 4;
Solution s;
bool res = s.hasPath(matrix, rows, cols, str);
cout << res << endl;
return 0;
}
matrix[i * cols + j]
/*这么写的原因是题目给出的矩阵是一个一维的数组矩阵,例如 a b c e s f c s a d e e ,
i:0-2, j: 0-3, 3行4列,但实际索引依次为从0-11,所以写成matrix[i * cols + j]的形式*/