剑指Offer 面试题12:矩阵中的路径
代码思路完全来自剑指Offer书中,因Java和c++的语言区别,有少量改动。代码整体思路都在代码注释中,仅供参考,共勉。
原题描述:
面试题12:矩阵中的路径
设计一个函数,判断在一个矩阵中是否存在包含某字符串的所有字符的路径。路径可以从任意一格开始,每步可以向上下左右移动一格。路径不能重复进入某一格子。
该面试题所在章节为 2.4.3回溯法 :从解决问题每一步的所有可能选项中系统地选择一个可行方案。重复选择,直至最终状态;或者某一步不满足条件,回溯到上一步;整个过程可以形象地用树状结构表示。
package chap2;
import java.util.Arrays;
/**
* 面试题12:矩阵中的路径
* @author hhz
*/
public class Problem12 {
/**
*
* @param matrix 字符矩阵
* @param rows 行数
* @param cols 列数
* @param str 字符数组
* @return
*/
public static boolean hasPath(char[][] matrix,int rows,int cols,char[] str){
//判断输入是否合法
if(matrix==null||rows<1||cols<1||str==null)
return false;
//标识矩阵中的某个格子是否已经包含在已有的路径中(路径不能重复进入一个格子)
boolean[] visited=new boolean[rows*cols];
int pathLength=0;
//不知道字符串开始字符在矩阵中的位置,需要遍历整个矩阵找到第一个字符串才能开始搜索路径
//找到第一个字符串位置后,后续工作都是hasPathCore做的了
for(int row=0;row<rows;row++){
for(int col=0;col<cols;col++){
if(hasPathCore(matrix,rows,cols,row,col,str,pathLength,visited)){
return true;
}
}
}
return false;
}
private static boolean hasPathCore(char[][] matrix, int rows, int cols, int row, int col, char[] str,
int pathLength, boolean[] visited) {
//pathLength都自增到末尾了,说明全部字符已找到
if(pathLength==str.length)
return true;
boolean hasPath=false;
if(row>=0&&row<rows&&col>=0&&col<cols&&matrix[row][col]==str[pathLength]&&!visited[row*cols+col]){
pathLength++;
visited[row*cols+col]=true;
boolean hasPathUp=false;
boolean hasPathDown=false;
boolean hasPathR=false;
boolean hasPathL=false;
//递归判断四个方向的情况
hasPathUp=hasPathCore(matrix,rows,cols,row,col-1,str,pathLength,visited);
hasPathDown=hasPathCore(matrix,rows,cols,row-1,col,str,pathLength,visited);
hasPathR=hasPathCore(matrix,rows,cols,row,col+1,str,pathLength,visited);
hasPathL=hasPathCore(matrix,rows,cols,row+1,col,str,pathLength,visited);
//四个方向只要有一个方向找到即可
hasPath=hasPathUp||hasPathDown||hasPathR||hasPathL;
//都找不到,那就是死胡同了,回溯到上一个位置
if(!hasPath){
pathLength--;
visited[row*cols+col]=false;
}
}
return hasPath;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
char[][] matrix={{'a','b','t','g'},{'c','f','c','s'},{'j','d','e','h'}};
char[] str={'b','f','c','e'};
boolean flag=hasPath(matrix, 3, 4, str);
System.out.println(flag);
String s=Arrays.deepToString(matrix);
System.out.println(s);
System.out.println(str);
}
}
改了一个错误,之前在递归求每个方向之前还加了判断下标是否越界的条件,做完面试题13后发现不需要这个判断。因为每次递归开始,实际上已经有了一个判断,不符合条件的直接返回结果了。之前的判断是多余的,碰到的数组越界错误应该是在row<rows这地方写错了,多加了一个等号。
测验代码输出如下:true
[[a, b, t, g], [c, f, c, s], [j, d, e, h]]
bfce