1.题目
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
a b c e
s f c s
a d e e
2.思路
首先对所整个矩阵遍历,找到第一个字符,然后向上下左右查找下一个字符,由于每个字符都是相同的判断方法(先判断当前字符是否相等,再向四周查找),因此采用递归函数。由于字符查找过后不能重复进入,所以还要定义一个与字符矩阵大小相同的布尔值矩阵,进入过的格子标记为true。如果不满足的情况下,需要进行回溯,此时,要将当前位置的布尔值标记回false。(所谓的回溯无非就是对使用过的字符进行标记和处理后的去标记)
3.代码实现
public class Solution {
public static boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
//这里对数组行列进行判断,故不需再做长度为0判断
if(matrix==null||rows<1||cols<1||str==null||str.length==0){
return false;
}
//将所有位置初始值都置为false
boolean [] isVisted=new boolean[rows*cols];
int strPath=0;
//数组中每个节点都可当作起点,进行查找
for(int row=0;row<rows;row++){
for(int col=0;col<cols;col++){
if(hasPathCore(matrix,rows,cols,row,col,str, strPath,isVisted))
return true;
}
}
return false;
}
private static boolean hasPathCore(char[] matrix, int rows, int cols, int row, int col, char[] str,int strPath, boolean[] isVisted) {
if(row<0||col<0||row>=rows||col>=cols|| //边界超出
isVisted[row*cols+col]==true|| //当前节点已被访问过
matrix[row*cols+col]!=str[strPath]){ //字符串的当前元素不匹配当前小格元素
return false;
}
if(strPath==str.length-1){
return true;
}
//代码可以走到这里,说明当前节点匹配字符串成功,当前节点置为true
isVisted[row*cols+col]=true;
boolean hasPath;
hasPath= hasPathCore(matrix,rows,cols,row-1,col, str,strPath+1, isVisted)||
hasPathCore(matrix,rows,cols,row+1,col, str,strPath+1, isVisted)||
hasPathCore(matrix,rows,cols,row,col-1, str,strPath+1, isVisted)||
hasPathCore(matrix,rows,cols,row,col+1, str,strPath+1, isVisted);
if(!hasPath){
//当前所在节点,任何方向都不通,回溯到前一个节点,得把当前节点重新置为false,以便其他路径可以通行
isVisted[row*cols+col]=false;
}
return hasPath;
}
//测试不存在的路径
// A B T G
// C F C S
// J D E H
@Test
public void test1() {
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "BFCTB".toCharArray();
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test1 passed.");
else
System.out.println("Test1 failed.");
}
//测试存在的路径
// A B T G
// C F C S
// J D E H
// BFCE
@Test
public void test2() {
char[] matrix = "ABTGCFCSJDEH".toCharArray();
int rows = 3;
int cols = 4;
char[] str = "BFCE".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
}
//测试只有1行
// A B T G
// BFCE
@Test
public void test3() {
char[] matrix = "ABTG".toCharArray();
int rows = 1;
int cols = 1;
char[] str = "A".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
}
//测试矩阵和路径中的所有字母都相同
// A B T G
// BFCE
@Test
public void test4() {
char[] matrix = "AAAA".toCharArray();
int rows = 1;
int cols = 1;
char[] str = "AAAA".toCharArray();
if (hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
}
//测试只有1列
// B
@Test
public void test5() {
char[] matrix = "B".toCharArray();
int rows = 1;
int cols = 1;
char[] str = "A".toCharArray();
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
}
//测试输入空字符串
@Test
public void test6() {
char[] matrix = "A".toCharArray();
int rows = 1;
int cols = 1;
char[] str = null;
if (!hasPath(matrix, rows, cols, str))
System.out.println("Test2 passed.");
else
System.out.println("Test2 failed.");
}
}