剑指Offer——JZ65 矩阵中的路径
题目描述
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子.例如 [ a b c e s f c s a d e e ] \begin{bmatrix}a &b&c&e \\ s&f&c&s \\ a&d&e&e\end{bmatrix} ⎣⎡asabfdcceese⎦⎤矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
题目分析
典型的DFS+回溯问题,矩阵中的每个点都可能为起点,因此需要双层循环进行遍历矩阵将每个点作为起点的情况进行分析。注意到有一些特别的地方是,本题中给的函数如下:
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
}
其中matrix无疑就是存储矩阵的数组,这里在代码里就需要进行一定的转换,计算矩阵在一维数组中的存储位置。
还有就是需要新定义一个函数用来判断当前位置的字符是否符合要求,并且用来进行递归和回溯。
代码
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
//用来标记当前格子是否已经被访问过
boolean[] flag = new boolean[matrix.length];
for(int i = 0;i < rows; i++){
for(int j = 0;j < cols; j++){
if(findPath(matrix,rows,cols,i,j,str,flag,0)){
return true;
}
}
}
return false;
}
public boolean findPath(char[] matrix,int rows,int cols,int i,int j,char[] str,boolean[] flag,int k){
//计算出矩阵在一维数组中的存储位置
int index = i * cols + j;
//此处的判断顺序尽量不要变更,因为JVM对 && 和 || 的处理具有短路的特性
//对于&&,JVM如果发现&&左边的表达式结果为false,就不再去计算右边的表达式
//对于||,JVM如果发现||左边的表达式结果为true,就不再去计算右边的表达式
//因此若将判断顺序颠倒,很有可能会造成因短路特性造成的程序错误
//判断条件:1.超出边界 2.当前位置已被访问过 3.当前位置的字符与目标字符串中对应位置的字符不相等
if(i < 0 || j < 0 || i >= rows || j >= cols || flag[index] == true || matrix[index] != str[k]){
return false;
}
//变量k就相当于一个计数器,用来存储当前符合要求的字符个数
//当k等于目标字符串的长度-1时,表示当前已经找到符合要求的一条路径,故返回true
if(k == str.length - 1){
return true;
}
//将当前位置的访问标志位置true
flag[index] = true;
//从当前位置出发,上下左右四个方向进行递归判断,只要能找到一条符合要求路径,即可返回true
if(findPath(matrix,rows,cols,i+1,j,str,flag,k+1)||
findPath(matrix,rows,cols,i-1,j,str,flag,k+1)||
findPath(matrix,rows,cols,i,j+1,str,flag,k+1)||
findPath(matrix,rows,cols,i,j-1,str,flag,k+1)){
return true;
}
//执行到这里,说明前面的判断是无法再进行下去的,说明此路不通,故需要回溯,将当前位置的访问标志位重置为false,同时返回false
flag[index] = false;
return false;
}
}

浙公网安备 33010602011771号