面试题12:矩阵中的路径
// 题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有
// 字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、
// 上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入
// 该格子。例如在下面的3×4的矩阵中包含一条字符串“bfce”的路径(路径中的字
// 母用下划线标出)。但矩阵中不包含字符串“abfb”的路径,因为字符串的第一个
// 字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入这个格子。
// A B T G
// C F C S
// J D E H
解题思路:
这是一个可以用回溯算法解决的问题。
首先任选一个格子开始走,如果第i次选择的这个格子的字符,恰好对应目标字符串第i个字符,
可以从这个格子的上下左右开始尝试寻找第i+1个字符,找到符合条件的继续往下走,否则就回退上一步。
(边边角角的就没有四个格子,相邻的只有2个或者3个,需要注意判断)
那么什么时候截止呢?当目标字符串的字符为'\0'就说明找到了一条路,函数就可以返回了。
由于题目的要求,进入一个格子后无法再次进入,所以应该有一个bool类型的数组记录已经组走过的路径。
伪代码:
bool hasPath(){ if(参数无效) return false; for(每行每列每个格子){ if(存在一条合法路径) return true; } return false; } bool hasPathCore(){ if(当前要寻找字符的是'\0') return true; if(行列合法&&格子当前字符==目标字符&&当前格子还未进入){ 标记此格子已进入; 字符向后移位; if(上下左右没有条路可以走通){ 字符向前回退; 标记此格子未进入; } } return; }
c/c++:
bool hasPath(const char* matrix, int rows, int cols, const char* str) { //校验参数有效性 if (matrix == nullptr || rows < 1 || cols < 1 || str == nullptr) return false; //标记格子是否被选中,初始化为false bool* visited = new bool[rows*cols]; memset(visited, 0, rows*cols); //从第0步,0行0列的格子开始走 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; } bool hasPathCore(const char* matrix, int rows, int cols, int row, int col, const char* str, int& pathLength, bool* visited) { //寻找路径结束 if (str[pathLength] == '\0') return true; bool hasPath = false; //当参数合法 //且目前要走的格子就是要寻找的路径下一步 if (row >= 0 && row < rows&&col >= 0 && col < cols && !visited[cols*row + col] && matrix[row*cols + col] == str[pathLength]) { //假设此路走得通,下一步
//标记此格子已经被选中 ++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 (!hasPath) { --pathLength; visited[row*cols + col] = false; } } return hasPath; }