题目:请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如
a b t g
c f c s
j d e h
这样的3 X 4 矩阵中包含一条字符串"b f c e"的路径,但是矩阵中不包含"a b f b"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路:遍历这个二维矩阵,从第一个开始判断满不满足 字符串,不满足就继续下一个,满足的话,递归判断再下一个满不满足,递归出口是我当前满足的字符串的已经走到末尾了,则矩阵中存在这样的一条字符串路径。
同时期间也要判断,我走过的地方就不能再走了,用一个数组来标志是否走过。
ac代码:
public class Solution {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str)
{
if(str == null) return false;
//保存当前节点是否被访问过
boolean visited[] = new boolean [rows*cols];
for(int i=0;i<visited.length;i++) visited[i] = false;
//System.out.println(visited.length);
int pathLength = 0; //当前已有的正确节点长度
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
if(hasPathCore(matrix,i,j,rows,cols,str,pathLength,visited))
return true;
}
}
return false;
}
public static boolean hasPathCore(char array[],int row,int col,int rows,int cols,char[] str,int pathLength,boolean visited[]) {
if(pathLength == str.length)
return true;
boolean hasPath = false;
//System.out.println("path = "+pathLength);
if(row >=0 &&row <rows && col>=0 && col <cols
&& array[row*cols+col] == str[pathLength] && !visited[row*cols+col]) {
//System.out.println(str[pathLength]);
pathLength++;
visited[row*cols+col] = true;
hasPath = hasPathCore(array, row, col-1,rows,cols, str, pathLength, visited) ||
hasPathCore(array, row, col+1, rows,cols,str, pathLength, visited) ||
hasPathCore(array, row-1, col,rows,cols, str, pathLength, visited) ||
hasPathCore(array, row+1, col, rows,cols,str, pathLength, visited);
if(!hasPath) {
pathLength --;
visited[row*cols+col] = false;
}
}
return hasPath;
}
}
完整代码:
public class twelveLuJing {
public static void main(String[] args) {
char [][] array = {
{'a','b','t','g'},
{'c','f','c','s'},
{'j','d','e','h'}
};
// char [] [] array = {
// {'A','B','C','E'},
// {'S','F','C','S'},
// {'A','D','E','E'}
// };
char str []= {'A','B','C','C'};
// System.out.println(array[0].length);
System.out.println(hasPath(array, str));
}
public static boolean hasPath(char array[][],char [] string) {
if(string == null) return false;
//保存当前节点是否被访问过
boolean visited[] = new boolean [array.length*array[0].length];
for(int i=0;i<visited.length;i++) visited[i] = false;
//System.out.println(visited.length);
int pathLength = 0; //当前已有的正确节点长度
for(int i=0;i<array.length;i++) {
for(int j=0;j<array[0].length;j++) {
if(hasPathCore(array,i,j,string,pathLength,visited))
return true;
}
}
return false;
}
public static boolean hasPathCore(char array[][],int row,int col,char[] str,int pathLength,boolean visited[]) {
if(pathLength == str.length)
return true;
boolean hasPath = false;
//System.out.println("path = "+pathLength);
if(row >=0 &&row <array.length && col>=0 && col <array[0].length
&& array[row][col] == str[pathLength] && !visited[row*array[0].length+col]) {
//System.out.println(str[pathLength]);
pathLength++;
visited[row*array[0].length+col] = true;
hasPath = hasPathCore(array, row, col-1, str, pathLength, visited) ||
hasPathCore(array, row, col+1, str, pathLength, visited) ||
hasPathCore(array, row-1, col, str, pathLength, visited) ||
hasPathCore(array, row+1, col, str, pathLength, visited);
if(!hasPath) {
pathLength --;
visited[row*array[0].length+col] = false;
}
}
return hasPath;
}
}
总结:回溯法适合解决一个问题,同时该问题下有多种子结构选择问题,类似于树结构,在满足当前节点的条件下,去遍历剩余的所有节点,从而找出最终的答案。
像解决迷宫类问题。