判断一个字符矩阵中是否存在着一条包含某个给定字符串的路径。
路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。
说明,从本道题开始使用牛客网的OJ以及参考相关大神的思路。
思路
考点为回溯法
待编辑,完善
解法1
/**
* 面试题12:矩阵中的路径
*
* @author Heroin X
* @date 2019/12/26 16:13
*/
public class PathMatrix {
public static void main(String[] args) {
char[] matrix={'a','b','t','g','c','f','c','s','j','d','e','h'};
int rows=3;int cols=4;
char[] str={'b','f','c','e'};
// char[] str={'a','b','f','b'};
boolean b = hasPath(matrix, rows, cols, str);
System.out.println(b);
}
public static boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
//还有特殊情况,第一个字符就找不到的时候
int[] firstPose = getFirstPose(matrix, str,cols);
int i=firstPose[0];int j=firstPose[1];
int[][] flag=new int[rows][cols];
return hasPath(matrix,rows,cols,str,i,j,flag,0);
}
private static boolean hasPath(char[] matrix, int rows, int cols, char[] str, int i, int j,int[][] flag,int index) {
//二维数组转化为一维数组,不懂为什么是这种写法?
int l=cols*i+j;
// int l=rows*i+j-1;
if (i<0 || i>=rows || j<0 || j>=cols || flag[i][j]==1 || matrix[l]!=str[index]){
return false;
}
// 表示全部匹配完成了
if (index==str.length-1){
return true;
}
// 走完了当前节点,置1
flag[i][j]=1;
if (hasPath(matrix,rows,cols,str,i-1,j,flag,index+1)
|| hasPath(matrix,rows,cols,str,i+1,j,flag,index+1)
|| hasPath(matrix,rows,cols,str,i,j-1,flag,index+1)
|| hasPath(matrix,rows,cols,str,i,j+1,flag,index+1)){
return true;
}
// 表示失败了
flag[i][j]=0;
return false;
}
/**
* 找到字符串首字符的位置
* @param matrix
* @param str
* @param cols
* @return
*/
static int[] getFirstPose(char[] matrix, char[] str,int cols){
for (int i=0;i<matrix.length;i++){
if (matrix[i]==str[0]){
int y = i % cols;
int x = i/cols;
return new int[]{x,y};
}
}
return new int[]{-1,-1};
}
}
解法2
nowcoder的AC
提交时间:2019-12-30 ,语言:Java ,运行时间: 29 ms ,占用内存:9632K ,状态:答案正确
(1)起始点的问题。解法1中的那种先找到起始点的方式在起始点有多个的情况下且第一个起始点不通时无法Accept,需要改进为解法2这种,从(0,0)坐标开始遍历。
(2)关于二维数组坐标与一维数组坐标位置转化的问题。int l=cols*i+j;
是OK的,而int l=rows*i+j-1;
实际是错我的,在于横纵坐标点位均是从0开始的。同时int x = i/cols; int y = i % cols;
是同样的道理。
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
int[][] flag=new int[rows][cols];
//从左上角(0,0)开始遍历
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
if(hasPath(matrix,rows,cols,str,i,j,flag,0)){
return true;
}
}
}
return false;
}
private boolean hasPath(char[] matrix, int rows, int cols, char[] str, int i, int j,int[][] flag,int index) {
//二维数组转化为一维数组,小心
int l=cols*i+j;
// int l=rows*i+j-1;
if (i<0 || i>=rows || j<0 || j>=cols || flag[i][j]==1 || matrix[l]!=str[index]){
return false;
}
// 表示全部匹配完成了
if (index==str.length-1){
return true;
}
// 走完了当前节点,置1
flag[i][j]=1;
if (hasPath(matrix,rows,cols,str,i-1,j,flag,index+1)
|| hasPath(matrix,rows,cols,str,i+1,j,flag,index+1)
|| hasPath(matrix,rows,cols,str,i,j-1,flag,index+1)
|| hasPath(matrix,rows,cols,str,i,j+1,flag,index+1)){
return true;
}
// 表示失败了
flag[i][j]=0;
return false;
}
}