(剑指offer)回溯法之矩阵中的路径
题目描述:
设计一个函数,用来判断在一个矩阵中是否存在包含某个字符串所有字符串的路径。路径可以从矩阵的任意一格开始,每一步可以在矩阵中向左,右,下移动任意一格。如果一条路径经过了矩阵的某一格,那么该路径不能再次进入该格子。
这是一个可以用回溯法解决的经典题。首先,在矩阵中任选一个格子作为路径的起点。假设矩阵中某个格子的字符为ch,并且这个格子将对应于路径上的第i个字符。如果路径上的第i字符不是ch,那么这个格子不可能处在路径上的第i个位置。如果路径上的第i个字符正好为ch,那么到相邻的格子寻找路径上的第i+1个字符。除矩阵边界上的格子之外,其他格子有4个相邻的格子。重复这个过程,直到路径上的所有字符都在矩阵中找到了相应的位置。
eg:
按步骤解析上述案例如下:
分析用回湖法解决问题的过程。由于矩阵的第一行第二个字母‘b’和路径"bfce"的第一个字符相等,我们就从这里开始分析。根据题目的要求,我们此时有 3个选项,分别是向左到达字母’a’向右到达字母’t’,向下到达字母’f’。我们先尝试选项’a’,由于此时不可能得到路径"bfce",因此不得不回到节点b尝试下一个选项t。同样,经过节点’t’也不可能得到路径"bfce"‘,因此再次回到节点’b’,尝试下一个选项f。
在节点甲我们也有3个选项,向左、向右都能到达字母’c’、向下到达字母’d’。我们先选择向左到达字母’c’,此时只有一个选择,即向下到达字母’j’。由于此时的路径为"bfcj",不满足题目的约束条件,我们只好回到上一个节点左边的节点’c’。注意到左边的节点’c’的所有选项都己经尝试过,因此只好再回溯到上一个节点’f’并尝试它的下一个选项,即向右到达节点’c’。
在右边的节点’c’我们有两个选择,即向右到达节点’s’,或者向下到达节点’e’。由于经过节点’s’不可能找到满足条件的路径,我们再选择节点’e’,此时路径上的宇母刚好组成字符串"bfce",满足题目的约束条件,因此我们找到了符合要求的解决方案。
Java代码解决方案:
public class MatrixPath {
public static void main(String[] args) {
String matrix="ABTGCFCSJDEH";
String target="ABFB";
if(!hasPath(matrix,3,4,target))
{
System.out.println("正确的,一针见血的");
}else{
System.out.println("错误的");
}
matrix="ABTGCFCSJDEH";
target="BFCE";
if(hasPath(matrix,3,4,target))
{
System.out.println("正确的,一针见血的");
}else{
System.out.println("错误的");
}
}
public static boolean hasPath(String matrix,int rows,int cols,String target)
{
if(matrix==null||cols<1||rows<1)
{
return false;
}
boolean visited[]=new boolean[rows*cols];
for(int i=0;i<rows*cols;i++)
{
visited[i]=false;
}
for(int i=0;i<rows;i++)
{
for(int j=0;j<cols;j++)
{
if(hasPathCore(matrix,rows,cols,i,j,target,0,visited))
{
return true;
}
}
}
return false;
}
public static boolean hasPathCore(String matrix,int rows,int cols,int row,int col,String target,int length,boolean[] visited)
{
if(length==target.length())
{
return true;
}
boolean hasPath=false;
if(row>=0&&row<rows&&col>=0&&col<cols&&matrix.charAt(cols*row+col)==target.charAt(length)&&!visited[row*cols+col])
{
visited[row*cols+col]=true;
hasPath=hasPathCore(matrix,rows,cols,row,col-1,target,length+1,visited)||hasPathCore(matrix,rows,cols,row,col+1,target,length+1,visited)||
hasPathCore(matrix,rows,cols,row+1,col,target,length+1,visited)||hasPathCore(matrix,rows,cols,row-1,col,target,length+1,visited);
if(!hasPath){
visited[row*cols+col]=false;
}
}
return hasPath;
}
}
``