题目描述
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
解题思路
可以看出来这道题涉及一个图的搜索,一般情况下图的搜索涉及到两种算法:深度优先算法(dfs)、广度优先算法(bfs)。广度优先搜索会根据离起点的距离,按照从近到远的顺序对各节点进行搜索。而深度优先搜索会沿着一条路径不断往下搜索直到不能再继续为止,然后再折返,开始搜索下一条路径。广度优先算法一般涉及的问题是需要求最短或者最优路径,而深度优先是求不出来最优路径的。对于这道题来说并不涉及最优路径问题我们就可以采取深度优先。首先把自己想象成一个站在图起点的人,这个图起点并不一定是board[0][0]点,起点取决于需要寻找的字符串的第一个字符,在图中找到第一个字符(多个)作为我每一次的起点,加入找到的第一个起点board[0][0]点,是现在我们可以水平走,也可以垂直走,也就是我可以上下左右走,但是要注意边界限制,还有就是我走过的点就再也不能走,每一次走我都走四种方向。步骤:
- 找到起点,进入搜索函数
- 判断当前点是否符合要求(是否被访问,是否超出边界,是否是和字符串匹配)
- 将当前点设置为已经访问过
- 进入上下左右四个点的搜索函数
- 设置回溯后取消点的访问
class Solution {
boolean used[][];//访问控制
public boolean exist(char[][] board, String word) {
if (board == null || board.length == 0 || board[0].length == 0) {
return false;
}
used = new boolean[board.length][board[0].length];
for (int i = 0;i < board.length;i++){
for(int j = 0;j < board[0].length;j++){
if(board[i][j] == word.charAt(0)){
if (dfs(board,word,0,i,j))//找到路径
return true;
}
}
}
return false;
}
public boolean dfs(char[][] board, String word,int index,int i,int j){
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || used[i][j]) //边界控制和访问控制
return false;
if (board[i][j] != word.charAt(index)) return false;//没找到
if (index == word.length() - 1){//最后一个找到了
return true;
}
used[i][j] = true;//访问board[i][j]方块
boolean res = dfs(board,word,index+1,i+1,j) || dfs(board,word,index+1,i-1,j)
|| dfs(board,word,index+1,i,j+1) || dfs(board,word,index+1,i,j-1) ;//四个方向都走
used[i][j] = false;//回退,取消访问
return res;
}
}