单词搜索
题目描述:
给定一个二维网格和一个单词,找出该单词是否存在于网格中。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。提示:board 和 word 中只包含大写和小写英文字母。1 <= board.length <= 2001 <= board[i].length <= 2001 <= word.length <= 10^3
示例
board =[['A','B','C','E'],['S','F','C','S'],['A','D','E','E']]给定 word = "ABCCED", 返回 true给定 word = "SEE", 返回 true给定 word = "ABCB", 返回 false
class Solution {
private char[][] board;
private String word;
private int len;
private int row;
private int col;
private boolean[][] used;
public boolean exist(char[][] board, String word) {
// 初始化
this.row = board.length;
this.col = board[0].length;
this.used = new boolean[row][col];
this.len = word.length();
this.board = board;
this.word = word;
for(int i = 0 ; i<row ; i++){
for(int j = 0 ; j<col ; j++){
if(board[i][j] == word.charAt(0) && DFS(i,j,0)) return true;
}
}
return false;
}
/**
* 第一、二个参数为当前的坐标
* 第三个参数为已经遍历word的下标
**/
private boolean DFS(int i,int j,int count){
// 这里的条件判断顺序不可打乱
if(count == this.len) return true;
if(i<0 || j<0 || i>=row || j>=col) return false; // 边界处理
if(this.used[i][j] || this.word.charAt(count) != this.board[i][j]) return false; // 查重处理&顺序处理
// char temp = board[i][j];
// board[i][j] = '.'; // 将非大小写字母符号赋予board[i][j],以避免"走回头路"
this.used[i][j] = true;
boolean flag = DFS(i-1,j,count+1) // 对上面进行递归
|| DFS(i+1,j,count+1) // 对下面进行递归
|| DFS(i,j-1,count+1) // 对左边进行递归
|| DFS(i,j+1,count+1); // 对右边进行递归
// board[i][j] = temp; // 还原
this.used[i][j] = false;
return flag;
}
}
典型的回溯算法。首先遍历board数组,从起始位置开始向上下左右分别递归,如果其中在count未达到最后word的长度前提下已经达到越过了边界,则说明只有word前面部分匹配,但是后面部分已经无法匹配,返回false;如果前面已经使用过board[i][j](即used[i][j] == true),而当前的位置为(i,j),一样的返回false,因为单元格内的字符不允许重复使用;如果当前位置的字符不等于word字符串的第count+1个字符,也是直接返回false;如果当前的count等于word的长度,则直接返回true。详细请看代码,读者有疑问的地方欢迎留言。