剑指–矩阵中的路径
1,题目:
2,思路:
深度优先搜索:
算法剖析:
- 1.递归参数: 当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k 。
- 2.终止条件:
- 3.返回 false : ① 行或列索引越界 或 ② 当前矩阵元素与目标字符不同 或 ③ 当前矩阵元素已访问过 (③ 可合并至 ② ) 。
- 4.返回 true : 字符串 word 已全部匹配,即 k = len(word) - 1 。
- 5.递推工作:
- 6.标记当前矩阵元素: 将 board[i][j] 值暂存于变量 tmp ,并修改为字符 ‘/’ ,代表此元素已访问过,防止之后搜索时重复访问。
- 7.搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需一条可行路径) ,并记录结果至 res 。
- 8.还原当前矩阵元素: 将 tmp 暂存值还原至 board[i][j] 元素。
- 9.回溯返回值: 返回 res ,代表是否搜索到目标字符串。
下面是对应的图解:
3,代码:
深度优先搜索:
class Solution {
public boolean exist(char[][] board, String word) {
/*
算法剖析:
1.递归参数: 当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k 。
2.终止条件:
3.返回 false : ① 行或列索引越界 或 ② 当前矩阵元素与目标字符不同 或 ③ 当前矩阵元素已访问过 (③ 可合并至 ② ) 。
4.返回 true : 字符串 word 已全部匹配,即 k = len(word) - 1 。
5.递推工作:
6.标记当前矩阵元素: 将 board[i][j] 值暂存于变量 tmp ,并修改为字符 '/' ,代表此元素已访问过,防止之后搜索时重复访问。
7.搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需一条可行路径) ,并记录结果至 res 。
8.还原当前矩阵元素: 将 tmp 暂存值还原至 board[i][j] 元素。
9.回溯返回值: 返回 res ,代表是否搜索到目标字符串。
*/
char[] words = word.toCharArray();
for(int i = 0; i < board.length; i++) {
for(int j = 0; j < board[0].length; j++) {
if(dfs(board, words, i, j, 0)) return true;
}
}
return false;
}
boolean dfs(char[][] board, char[] word, int i, int j, int k) {
if(i >= board.length || i < 0 || j >= board[0].length || j < 0 || board[i][j] != word[k]) return false;
if(k == word.length - 1) return true;//字符串 word 已全部匹配,即 k = len(word) - 1 。
char tmp = board[i][j];
board[i][j] = '/';//将 board[i][j] 值暂存于变量 tmp ,并修改为字符 '/' ,代表此元素已访问过,防止之后搜索时重复访问。
boolean res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) ||
dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
//搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需一条可行路径) ,并记录结果至 res 。
board[i][j] = tmp;//还原当前矩阵元素: 将 tmp 暂存值还原至 board[i][j] 元素。
return res;
}
}
另一种写法(也是深度优先搜索):
class Solution {
boolean res=false;
int row,col;
public boolean exist(char[][] board, String word) {
if(word.length()==0)return res;
char []words=word.toCharArray();
row=board.length;
col=board[0].length;
if(row*col<words.length)return res;
for(int i=0;i<row&&res==false;i++){//遍历board,res为true时可以直接返回了。
for(int j=0;j<col;j++){
if(words[0]==board[i][j]){
dfs(board,words,i,j,0);
}
}
}
return res;
}
private void dfs(char[][] board, char[] word,int i,int j,int index){
if(res||board[i][j]!=word[index])return;//找到满足的路径或路径不正确
if(word.length-1==index){//找到满足的路径
res=true;
return;
}
char temp= board[i][j];
board[i][j]='#';//标记路径
if(i+1<row&&board[i+1][j]!='#')dfs(board,word,i+1,j,index+1);//下
if(i>0&&board[i-1][j]!='#')dfs(board,word,i-1,j,index+1);//上
if(j+1<col&&board[i][j+1]!='#')dfs(board,word,i,j+1,index+1);//右
if(j>0&&board[i][j-1]!='#')dfs(board,word,i,j-1,index+1);//左
board[i][j]=temp;//撤销选择
}
}