前言
一、题目介绍
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
示例:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
二、解题思路
1.分析题目
针对题目给出的介绍和示例,可以分析,题目是想让我们查找一个矩阵中是否可以找到给出的单词,也就是所谓的单词搜索,我们可以思考一下,其实也就是搜索,我们把矩阵想象成图,也就是从一个图中搜索一个单词,可以尝试图的搜索算法,深度和广度优先搜索遍历。
2.思路与算法
当确定完是搜索的话,可以尝试深度搜索遍历。
我们可以尝试从矩阵的每一个位置开始搜索,如果当前位置的字符和单词开始字符相同,则单词字符后移一位,矩阵往下一个方位搜索,一共有四个可供选择的方向。如果一直下去都可以搜到对应的矩阵字符与单词字符相匹配,则就返回true,如果有一个字符不匹配,则返回false,下次从下一个矩阵位置开始从0字符开始搜索,一直遍历完所有的矩阵位置。
对每次遍历,如果当前位置已经遍历过需要进行标记,可以使用一个同矩阵大小的标记矩阵visited[][]。
3.代码部分
Java代码详细注释
class Solution {
public boolean exist(char[][] board, String word) {
//使用深度优先搜索遍历
int row = board.length;
int low = board[0].length;//获取数组的大小
//设置一个判断数组,判断当前数组是否已经访问过
boolean [][]visited = new boolean[row][low];//默认的是false
for(int i = 0;i<row;i++){
for(int j = 0;j<low;j++){
boolean flag = check(visited,board,i,j,word,0);//依次检查当前节点
if (flag){//找到单词的匹配,返回true
return true;
}
}
}
return false;//没找到返回false
}
//检查函数
public boolean check(boolean [][]visited,char[][]board,int i,int j,String word,int k){
//先检查当前数组所对应的节点是否存在单词的字母
if(board[i][j]!=word.charAt(k)){
return false;
}
//如果当前已经遍历到单词的最后一个字母,则直接返回
else if(k == word.length()-1){
return true;//也就是单词匹配成功
}
visited[i][j] = true;//已经比对过当前节点,而且说明当前点对应的字母匹配上了。
boolean result = false;//判断参数
int[][] directions = {{0,1},{0,-1},{1,0},{-1,0}};//当遍历到一个节点后,下次可以往四个方向查找,{0,1}代表东边,{0,-1}代表北边,{1,0}代表南边{-1,0}代表西边。
//下一步,查找四周的四个点是否存在匹配的字母
for(int[]dir:directions){//使用增强for,直接获取当前directions中的数据,并不是获取索引。
int newi = i + dir[0],newj = j + dir[1];//新的查找节点
if(newi>=0 && newi<board.length &&newj>=0 && newj<board[0].length){//边界判断
if(visited[newi][newj]!=true){//判断当前节点是否访问,如果没有在进行下一步判断
boolean flag = check(visited,board,newi,newj,word,k+1);
if(flag){//如果返回的是true,说明是匹配的。
result = true;
break;
}
}
}
}
visited[i][j] = false;//检查完当前节点需要把其重新变回false,便于下次检查使用
return result;//返回结果
}
}
三、总结
提示:针对个别类型的题目,可以直接套用深度优先搜索遍历,其实可以总结出这种类型题目的模板,也就是深度优先搜索遍历的模板。
dfs(){
// 第一步,检查下标是否满足条件
// 第二步:检查是否被访问过,或者是否满足当前匹配条件
// 第三步:检查是否满足返回结果条件
// 第四步:都没有返回,说明应该进行下一步递归
// 标记
dfs(下一次)
// 回溯
}
main() {
for (对所有可能情况) {
dfs()
}
}
记录时间:2020年12月8日