给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
这个问题要求我们在一个二维字符网格中找到一个给定的单词。单词必须按照字母顺序,通过相邻的单元格内的字母构成,同一个单元格内的字母不允许被重复使用。
可以使用深度优先搜索来解决这个问题。从网格中的每个单元格开始搜索,如果当前单元格的字母与单词的第一个字母匹配,我们就继续搜索相邻的单元格,直到找到单词的最后一个字母或者搜索失败。
算法步骤
- 创建一个函数,接受三个参数:board(二维字符网格),word(要搜索的单词),和(i,j)(当前搜索的单元格坐标)。
- 检查当前单元格的字母是否与单词的第一个字母匹配。如果不匹配,返回false。
- 如果当前单元格的字母与单词的第一个字母匹配,将当前单元格标记为已访问,防止重复使用。
- 如果单词的长度为1,返回true,表示找到了单词。
- 递归调用函数,搜索相邻的单元格,传递单词的剩余部分和相邻单元格的坐标。
- 如果相邻单元格的搜索成功,返回true。
- 如果相邻单元格的搜索失败,将当前单元格标记为未访问,并返回false。
public class no_79 {
public static void main(String[] args) {
char[][] board = {
{'A', 'B', 'C', 'E'},
{'S', 'F', 'C', 'S'},
{'A', 'D', 'E', 'E'}
};
String word = "ABCCED";
System.out.println(exist(board, word));
}
public static boolean exist(char[][] board, String word) {
int m = board.length;
int n = board[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(board, word, i, j, 0)) return true;
}
}
return false;
}
private static boolean dfs(char[][] board, String word, int i, int j, int index) {
if (index == word.length()) return true;
if (i < 0 || i >= board.length || j < 0 || j >= board[0].length || board[i][j] != word.charAt(index))
return false;
char temp = board[i][j];
board[i][j] = '#';
boolean found = dfs(board, word, i + 1, j, index + 1)
|| dfs(board, word, i - 1, j, index + 1)
|| dfs(board, word, i, j + 1, index + 1)
|| dfs(board, word, i, j - 1, index + 1);
board[i][j] = temp;
return found;
}
}
讲一下思路,代码还是比较易懂的,首先在exist函数中将数组中每个字符都能作为起始点,这点需要注意,之前的回溯题目都是第一个开始,这道题可以从任何一个位置开始。
需要带入dfs函数的数据有:字符数组(不变),要查找的字符串(不变),当前位置开始查找单词的索引i,j,以及当前查找到字符串的字母的位置。
在查找中,首先将当前的字符变成'#',以免之后的查找路径重复查找到当前字符,然后将周围的四个位置的字母一并带入,只要有一个符合下一个index字母,那么就返回true,再在下一个字符处寻找。
函数返回条件就是index == word.length,代表一直找到了word的最后一个字符,如果超出边界索引就返回false。