难度中等
题目描述:
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true
示例 2:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" 输出:true
示例 3:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" 输出:false
提示:
m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board
和word
仅由大小写英文字母组成
具体代码实现:
class Solution {
public boolean exist(char[][] board, String word) {
int h = board.length,w = board[0].length;//网格的长和宽
boolean[][] visited = new boolean[h][w];//标记是否访问过的数组
for(int i = 0; i < h; i++){
for(int j = 0; j< w; j++){
boolean flag = check(board,visited,i,j,word,0);
if(flag){
return true;
}
}
}
return false;
}
//检查从网格i,j出发是否能搜索到0~k的字符组成的子串
public boolean check(char[][] board, boolean[][] visited, int i, int j, String s, int k){
//如果i,j位置的字符和第k个的字符不相等,则这条搜索路径搜索失败返回false
if(board[i][j] != s.charAt(k)){
return false;
}else if(k == s.length() - 1){
//如果搜索到了字符串的结尾,则找到了网格中的一条路径,这条路径上的字符正好可以组成字符串S,返回true
return true;
}
visited[i][j] = true;//标记i,j被访问过了
int[][] directions = {{0,1}, {0,-1}, {1,0}, {-1,0}};//方向数组
boolean result = false;
for(int[] dir : directions){ //向i,j的四个方向继续尝试寻找
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]){//新的坐标不能存在于visited中,也就是不能是访问过的
boolean flag = check(board, visited, newi, newj, s, k+1);//继续检查新的坐标
if(flag){//如果在网格中找到了字符串则跳过循环
result = true;
break;
}
}
}
}
visited[i][j] = false;//回溯状态
return result;//返回结果
}
}