给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
board =
[
[‘A’,‘B’,‘C’,‘E’],
[‘S’,‘F’,‘C’,‘S’],
[‘A’,‘D’,‘E’,‘E’]
]
给定 word = “ABCCED”, 返回 true
给定 word = “SEE”, 返回 true
给定 word = “ABCB”, 返回 false
分析:该题只能使用搜索,设置一个标志数组记录是否访问过,若访问过,则不能在访问,同时边界条件要注意 注释掉的错误写法
class Solution {
public boolean exist(char[][] board, String word) {
//用过的单词不能再用。选择列表是哪些未被选择的字母,同时必须左右上下相邻
//创建一个visited二维数组记录 访问状态,默认为false 没有访问过
boolean visited[][] = new boolean[board.length][board[0].length];
for(int i = 0; i < board.length;i++){
for(int j = 0;j <board[0].length;j++){
boolean ans = dfs(visited,word,i,j,0,board);
if(ans){
return true;
}
}
}
//到这里说明没有找到
return false;
}
//k代表当前匹配word中的第几个字符
public boolean dfs(boolean [][]visited,String word,int i,int j,int k,char[][] board){
//这样写法错误,因为有可能最后一个字符不相等也返回true
// if(k == word.length() - 1){
// return true;
// }else if(board[i][j] != word.charAt(k)){
// return false;
// }
//
if(board[i][j] != word.charAt(k)){
return false;
}else if(k == word.length() - 1){//到这说明 第k个字符相等 且到达最后 !!!注意不可以写成上面注释掉的边界条件
return true;
}
//进入这里说明当前字符和目标字符相等,且还没有到达单词结尾
//将当前节点标记为访问过
visited[i][j] = true;
//有四个方向可以查询
int[][] directions = {{0,-1},{0,1},{1,0},{-1,0}};
//设置一个变量存储结果
//默认设置为false
boolean result = false;
//分别像这四个方向
for(int[]dir:directions){
int newi = i +dir[0],newj = j+dir[1];
//如果新的i和j没有越界的话 就查找
if(newi>=0&&newi<board.length&&newj>=0&&newj<board[0].length){
//同时字母没有被访问过的前提下
if(!visited[newi][newj]){
boolean flag = dfs(visited,word,newi,newj,k+1,board);
if(flag == true){
//将答案更新为true
result = true;
break;
}
}
}
}
//这里是四个方向都已经查找完毕
//回溯 设置为没有访问过该点
visited[i][j] = false;
return result;
}
}