「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战」
前言
力扣第七十九题 单词搜索 如下所示:
给定一个 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
一、思路
这一题的题目中有两个比较重要的信息:
- 在网格
board中选择的字符都是相邻的 - 网格
board中的每个字符只能选择一次
每个字符只能选择一次比较好解决,我们可以使用一个二维数组来存储该位置上的字符是否已经选择了。
那如何由相邻字符组成的单词呢?
我们可以使用递归来解决这一问题,我们定义递归的函数为:找到以网格中的 i, j 作为起点,是否能找到单词中的第 k 个元素(有四个方向:向上、向下、向左、向右)。
既然想法有了,实现起来也就不苦难了。大致的步骤如下所示:
- 遍历网格
board - 判断
board[i][j]是否等于单词中的第一个字符,如果不想等,则继续遍历网格。如果相等,则继续判断以i, j为起点是否能找到单词中的下一个字符 - 只要能够找到一组结果就立即返回
true即可
举个例子
此处以示例中的 board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" 作为例子
- 遍历网格
board - 当
i=1, j=0时,出现了board[1][0] = word[0]。故继续以i=1, j=0作为起点,无法继续匹配,故终止 - 当
i=1, j=3时,出现了board[1][3] = word[0]
继续以i=1, j=3作为起点,可找到board[2][3] = word[1]
再以i=2, j=3作为起点,可找到board[2][2] = word[2] - 最终找到了一组正确的结果,返回
true即可
二、实现
实现代码
值得注意的是:当找到一组结果后,应立即停止,无需再寻找了,防止正确结果被更新。
int[][] selected;
public boolean exist(char[][] board, String word) {
selected = new int[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)) {
selected[i][j] = 1;
if (dfs(i, j, board, 1, word)) {
return true;
}
selected[i][j] = 0;
}
}
}
return false;
}
public boolean dfs(int i, int j, char[][] board, int k, String word){
boolean flag = false;
if (k == word.length())
return true;
if (i-1 > -1 && selected[i-1][j] == 0 && word.charAt(k) == board[i-1][j]) { // 向上
selected[i-1][j] = 1;
flag = dfs(i-1, j, board, k+1, word);
selected[i-1][j] = 0;
}
if(!flag && i+1 < board.length && selected[i+1][j] == 0 && word.charAt(k) == board[i+1][j]) { // 向下
selected[i+1][j] = 1;
flag = dfs(i+1, j, board, k+1, word);
selected[i+1][j] = 0;
}
if(!flag && j-1 > -1 && selected[i][j-1] == 0 && word.charAt(k) == board[i][j-1]) { // 向左
selected[i][j-1] = 1;
flag = dfs(i, j-1, board, k+1, word);
selected[i][j-1] = 0;
}
if(!flag && j+1 < board[0].length && selected[i][j+1] == 0 && word.charAt(k) == board[i][j+1]) { // 向左
selected[i][j+1] = 1;
flag = dfs(i, j+1, board, k+1, word);
selected[i][j+1] = 0;
}
return flag;
}
测试代码
public static void main(String[] args) {
// board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
char[][] board = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
char[][] board1 = {{'a', 'b'}};
char[][] board2 = {{'C','A','A'},{'A','A','A'},{'B','C','D'}};
boolean flag = new Number79().exist(board, "SEE");
System.out.println(flag);
}
结果
三、总结
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~