《剑指Offer》Java刷题 NO.65 矩阵中的路径(数组、DFS、回溯法、是否存在路径)
传送门:《剑指Offer刷题总目录》
时间:2020-07-27
题目:
请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如下图 矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
思路:
- 其实是DFS的思想,对每个点做DFS,只不过DFS是为了寻找所有可能路径,这道题是判断是否存在一条路径,所以只要有一条是符合的就可以直接返回了;
- 另外在做DFS的时候可以剪枝,只要当前位置的字符和字符串对应位置的字符无法匹配,就返回false,不用再看四个方向了;如果可以匹配,就递归四个方向看,只要任意一个方向可以返回true就说明可以匹配成功
- 注意返回上一层的时候,也就是回溯的时候,要把当前字符重新标记为未访问,因为只需要保证同一条路径不能经过同一个格子,不同的路径是可以的
注意: 这个题目里面是用一维数组保存的矩阵
DFS模板
int check(参数)
{
if(满足条件)
return 1;
return 0;
}
void dfs(int step)
{
标记
判断边界
{
相应操作
}
尝试每一种可能
{
满足check条件//可以是判断该元素有没有被访问过
//也可以在这里做标记
继续下一步dfs(step+1)
恢复初始状态(回溯的时候要用到)//!!!回溯的时候很重要
}
}
Java代码:
/**
* @author LiMin
* @Title: HasPath
* @Description: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。
* @date 2020/7/28 9:27
*/
public class HasPath {
public static void main(String[] args) {
HasPath has = new HasPath();
char[] matrix = "ABCESFCSADEE".toCharArray();
char[] str = "ABCCED".toCharArray();
System.out.println(has.hasPath(matrix, 3, 4, str));
}
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
if (matrix == null || matrix.length == 0 || matrix.length < str.length || str == null || str.length <= 0) {
return false;
}
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (dfs(matrix, rows, cols, str, 0, j, i)) {
return true;//剪枝
}
}
}
return false;
}
public boolean dfs(char[] matrix, int rows, int cols, char[] str, int step, int x, int y) {
int index = cols * y + x;//先计算出(x,y)在一维数组中的索引值
//判断边界和check条件
if (x < 0 || x >= cols || y < 0 || y >= rows || matrix[index] == '#' || matrix[index] != str[step]) {
return false;
}
if (step == str.length - 1) {
return true;//匹配成功的截止条件
}
//当前字符可以匹配,标记为已访问,这里不用再专门申请一个标记数组了
char c = matrix[index];
matrix[index] = '#';
//递归检查四个方向是否至少有一个可以完全匹配,只要有一个匹配就可以返回了,所以用“或”来连接
if (dfs(matrix, rows, cols, str, step + 1, x + 1, y) || dfs(matrix, rows, cols, str, step + 1, x - 1, y)
|| dfs(matrix, rows, cols, str, step + 1, x, y - 1) || dfs(matrix, rows, cols, str,step + 1, x, y + 1)) {
return true;//剪枝
}
//回溯:当前字符在当前路径的step不匹配,但是之后可以出现在其他路径,所以应该重新标记为未访问;另外step因为递归调用被压栈,返回上一层可以自动减一
matrix[index] = c;
//走到这还没返回说明走不通
return false;
}
}