文章目录
- 79. 单词搜索
- 解题
- 方法:回溯
79. 单词搜索
79. 单词搜索 给定一个 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 仅由大小写英文字母组成
进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board 更大的情况下可以更快解决问题?
解题
方法:回溯
dfs + 回溯,时间O(MN3^ L)。空间O(MN) , M,N 为网格的长度与宽度,L为字符串 word 的长度, 然而,由于剪枝的存在,我们在遇到不匹配或已访问的字符时会提前退出,终止递归流程。因此,实际的时间复杂度会远远小于O(MN3^L)
class Solution {
// 回溯
public boolean exist(char[][] board, String word) {
// 行数
int row = board.length;
// 列数
int col = board[0].length;
// 标记数组,默认为false
boolean[][] used = new boolean[row][col];
// 遍历board数组,遇到单词的第一个字符进入搜索
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == word.charAt(0)) {
// 参数含义:网格数组、当前下标,标记数组,单词,单词下标
boolean flag = dfs(board, i, j, used, word, 0);
if (flag == true) {
return true;
}
}
}
}
return false;
}
// 参数含义:网格数组、当前下标,标记数组,单词,单词下标
private boolean dfs(char[][] board, int i, int j, boolean[][] used, String word, int k) {
// 条件判断
// 单词到了最后一个字符, 说明单词存在
if (k >= word.length()) {
return true;
}
// 判断 i j 的边界
if(i<0 || i>=board.length || j<0 || j>=board[0].length){
return false;
}
// 判断是否使用过
if (used[i][j] == true) {
return false;
}
// 判断字符是否相等
if (board[i][j] != word.charAt(k)) {
return false;
}
// 经过上面的判断,说明board[i][j] == word.charAt(k),需要判断次位置的上下左右了
used[i][j] = true;
// 上
boolean flag1 = dfs(board, i - 1, j, used, word, k+1);
if(flag1){
return true;
}
// 下
boolean flag2 = dfs(board, i + 1, j, used, word, k+1);
if(flag2){
return true;
}
boolean flag3 = dfs(board, i, j - 1, used, word, k+1);
if(flag3){
return true;
}
boolean flag4 = dfs(board, i, j + 1, used, word, k+1);
if(flag4){
return true;
}
// 回溯操作,以单词开头字符的这一次搜索结束,方便下一个单词开头字符的搜索
used[i][j] = false;
return false;
}
}