剑指 Offer 12. 矩阵中的路径
深度优先搜索(dfs):去遍历所有的可能性
PS:for循环中continue是中止本次循环。
break是完全中止所有循环。
1.矩阵中方向数组的使用
int[] dx = {0, 1, 0, -1}, dy = {1, 0, -1, 0};
//(0,1)和(1,0)和(0,-1)和(-1,0)分别对应着上下左右
2.减枝
u == len目的:每次dfs只招符合单词长度的步数。超过单词长度的直接返回。
只有找到才会u+1;
if(u == len || res){
res = true;
return;
}
3.标记已经被dfs
f[i][j] = true;
dfs(1, i, j);
f[i][j] = false;
boolean[][] f;
// 标记搜索的过程中格子是否被使用过
f = new boolean[n][m];
class Solution {
//结果
boolean res = false;
//len 目标串的长度,矩阵 n列 m行
int n, m, len;
//用来标记是否被使用过
boolean[][] f;
//把字符串转化成字符数组toCharArray()
char[] s;
//复制矩阵
char[][] b;
public boolean exist(char[][] board, String word) {
b = board;
s = word.toCharArray();
// 目标串的长度
len = s.length;
n = board.length;
m = board[0].length;
// 标记搜索的过程中格子是否被使用过
f = new boolean[n][m];
// 找到与目标串第一个字符相同的格子,开始搜索
for(int i = 0; i < n ; i ++){
for(int j = 0; j < m; j ++){
if(s[0] == board[i][j]){
f[i][j] = true;
dfs(1, i, j);
f[i][j] = false;
}
// 每次搜索后判断是否已经找到
if(res){
return true;
}
}
}
return false;
}
public void dfs(int u, int i, int j){
// u == len 终止条件
// res 如果已经找到,则直接return (剪枝)
// 这里要加res的原因主要是为了剪去不需要的搜索
// 这里是优化了后面代码中的一个dfs搜索
// 如果在某一次循环中找到了结果,就直接退出
// 如果没加上res判断,由于要判断四个方格,程序会继续判断下一个方格,这里就是无用的搜索,直接剪去即可
if(u == len || res){
res = true;
return;
}
// 方向数组
int[] dx = {0, 1, 0, -1}, dy = {1, 0, -1, 0};
for(int d = 0; d < 4; d ++){
int x = i + dx[d], y = j + dy[d];
// 坐标越界 或者 当前格子已经被使用了 就直接结束此次循环
if(x < 0 || y < 0 || x >= n || y >= m || f[x][y]){
continue;
}
if(b[x][y] == s[u]){
// 标记被使用
f[x][y] = true;
// 这里找到答案回溯后,下一个循环会继续进入dfs函数
// 也就是在下一个循环做无用的搜索,这里也是为什么要判断res的原因
// 或者你可以在这行代码之后判断res,然后退出
dfs(u + 1, x, y);
// 恢复现场
f[x][y] = false;
}
}
}
}