矩阵中的路径
约 786 字大约 3 分钟
题目:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含否字符串所有字符的路径。路径可以从矩阵中任意一格开始,每一步可以在矩阵中向左、右、上、下移动一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。例如,在下面的 3x4 的矩阵中包含一条字符串 “bfce” 的路径(路径中的字母用下划线标出)。但矩阵中不包含字符串 “abfd” 的路径,因为字符串的第一个字符 b 占据了矩阵中的第一行第二个格子之后,路径不能再进入这个格子。
a b t g
c f c s
j d e g
分析:本题可以使用回溯法。
回溯法:
回溯算法实际上是一个类似枚举的搜索尝试过程,在搜索过程中寻找问题的解,当发现当前问题状态无解时,就 “回溯” 返回,尝试别的路径。
判断回溯很简单,拿到一个问题,你感觉如果不穷举一下就没法知道答案,那就可以开始回溯了。
这个一个走路径的问题,需要判断这个矩阵中的每一个结点是否可以走一条路径,在走的过程中,设置一个和矩阵大小相同的整型数组表示是否已经访问,如果某个结点访问了,那么该结点的是否访问则为1。每次遍历一个结点的时候,递归的方式分别向左、向右、向上、向下。
代码:
/**
* 判断路径是否存在
*
* @param matrix 矩阵,用二维数组表示
* @param rows 总行数
* @param cols 总列数
* @param path 要查找的路径
*/
public static boolean hasPath(char[][] matrix, int rows, int cols, char[] path) {
int[] flag = new int[rows * cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (hasChar(matrix, rows, cols, i, j, path, 0, flag)) {
return true;
}
}
}
return false;
}
/**
* 判断字符是否存在
*
* @param matrix 矩阵,用二维数组表示
* @param rows 总行数
* @param cols 总列数
* @param row 当前行
* @param col 当前列
* @param path 查找路径
* @param index path中下标
* @param flag 已访问元素标记
*/
private static boolean hasChar(char[][] matrix, int rows, int cols, int row, int col, char[] path, int index, int[] flag) {
// 判断字符是否被使用过的位置标记
int unique = row * cols + col;
// 不是要访问的字符,或者已经被访问过,直接返回false
if (row < 0 || row >= rows || col < 0 || col >= cols || matrix[row][col] != path[index] || flag[unique] == 1) {
return false;
}
// 已经是path里面最后一个字符
if (index == path.length - 1) {
return true;
}
// 标记为已访问
flag[unique] = 1;
// 分别向上、向下、向左、向右遍历
if (hasChar(matrix, rows, cols, row - 1, col, path, index + 1, flag)
|| hasChar(matrix, rows, cols, row + 1, col, path, index + 1, flag)
|| hasChar(matrix, rows, cols, row, col - 1, path, index + 1, flag)
|| hasChar(matrix, rows, cols, row, col + 1, path, index + 1, flag)) {
return true;
}
flag[unique] = 0;
return false;
}