一、题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
对一个判断矩阵和字符串b,c,e,找到判断矩阵中是否存在bce的路径,解题思路如下。
二、解答
解题思路:回溯法,矩阵中的每一个元素都有可能是路径的起点。依次遍历矩阵中的每一个元素,对于当前元素,下一步可以是前、左、右。每进行下一步就判断一下是否匹配对应下标索引的字符串,如果匹配继续往前走,如果不匹配则回退一步,选择其他两个方向之一。一直匹配字符串中的所有字符返回true 否则返回false。
实现代码如下:
public static boolean hasPath(char[] matrix,int rows,int cols, char[] str){
if(matrix==null||str==null)
return false;
char[][] matrix1 = new char[rows][cols];
//把一维矩阵转换为二维矩阵
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++){
matrix1[i][j] = matrix[i*cols+j];
}
}
//定义访问矩阵,并初始化
boolean[][] visa = new boolean[rows][cols];
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
visa[i][j] =false;
}
}
int strLenth =0;
//依次遍历矩阵中的每一个元素
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
if(hasPathCore(matrix1,str,visa,i,j,strLenth)) {
return true;
}
}
}
return false;
}
//判断是否包含字符串中的路径
private static boolean hasPathCore(char[][] matrix, char[] str, boolean[][] visa,int i, int j, int strLength) {
//二维矩阵的行
int rows = matrix.length;
//二维矩阵的列
int col = matrix[0].length;
//判断是否走完字符串的长度
if(strLength == str.length) {
return true;
}
boolean hasPath = false;
//条件约束
if (i >= 0 && i <rows && j >= 0 && j < col && matrix[i][j] == str[strLength] &&
visa[i][j] == false) {
visa[i][j] = true;
strLength++;
//递归
hasPath = hasPathCore(matrix, str, visa, i, j-1,strLength)||hasPathCore(matrix, str, visa, i - 1, j, strLength)
||hasPathCore(matrix, str, visa, i, j + 1, strLength)||hasPathCore(matrix, str, visa, i + 1, j, strLength);
//没有路径,则回退一步
if(!hasPath) {
strLength--;
visa[i][j] = false;
}
}
return hasPath;
}
//测试
public static void main(String[] args) {
char[] matrix = new char[] {'a','b','c','d','e','f','g','u','b','c','a','m'};
char[] str = new char[] {'a','b','c','d'};
boolean bool = hasPath(matrix,3,4,str);
System.out.println(bool);
}