大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!
精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。
博客主页:知识汲取者的博客
LeetCode热题100专栏:LeetCode热题100
Gitee地址:知识汲取者 (aghp) - Gitee.com
Github地址:Chinafrfq · GitHub
题目来源:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台
PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激
原题链接:79.单词搜索
解法一:BFS+剪枝
/**
* @author ghp
* @date 2023/6/17
* @title
* @description
*/
class Solution {
private boolean f = false;
private boolean[][] vis;
private int[][] dir = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public boolean exist(char[][] board, String word) {
int m = board.length;
int n = board[0].length;
if (m == 1 && n == 1) {
// 单独处理board只有一个元素的情况
return word.equals("" + board[0][0]);
}
vis = new boolean[m][n]; // 用于判断当前节点是否已遍历
// 从每一个节点出发,进行深搜
for (int i = 0; i < board.length; i++) {
if (f){
// 一但f边为true,就直接停止搜索,节省时间
break;
}
for (int j = 0; j < board[0].length; j++) {
dfs(board, word, new StringBuilder(), i, j);
}
}
return f;
}
private void dfs(char[][] board, String word, StringBuilder path, int r, int c) {
if (f){
// 已经从board中找到了word,没必要再搜索了
}
if (r >= board.length || r < 0 || c == board[0].length || c < 0) {
// 越界
return;
}
if (!word.substring(0, path.length()).equals(path.toString())) {
// 剪枝(当前路径已经出现一个不符合word的单词了,结束本次搜索)
return;
}
if (path.length() == word.length()) {
// 已经在board中找到了word,结束循环
f = true;
return;
}
for (int i = 0; i < 4; i++) {
if (!vis[r][c]) {
// 当前节点没有被遍历过,搜索下一个节点,并将当前节点标记为true
path.append(board[r][c]);
vis[r][c] = true;
bfs(board, word, path, r + dir[i][0], c + dir[i][1]);
// 恢复现场,用于回溯
path.deleteCharAt(path.length() - 1);
vis[r][c] = false;
}
}
}
}
复杂度分析:
其中m和n分别是board数组的行数和列数,L是word字符串的长度
代码优化:
/**
* @author ghp
* @date 2023/6/17
* @title
* @description
*/
class Solution {
public boolean exist(char[][] board, String word) {
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[0].length; j++) {
if (dfs(board, word, 0, i, j)) {
return true;
}
}
}
return false;
}
private boolean dfs(char[][] board, String word, int index, int r, int c) {
if (r > board.length - 1 || r < 0 || c > board[0].length - 1 || c < 0 // 越界,结束递归
|| board[r][c] == '.' // 当前节点已遍历,结束递归
|| board[r][c] != word.charAt(index)) { // 当前路径已经出现一个不符合的单词了,结束递归
return false;
}
if (index == word.length() - 1) {
// index的长度等于word(因为从0开始计数,所以word长度要-1),说明已经再board中找到了word
return true;
} else {
// 当前节点没有遍历,则置为.表示已遍历,然后遍历四个方向
char temp = board[r][c];
board[r][c] = '.';
boolean f = dfs(board, word, index + 1, r + 1, c) || dfs(board, word, index + 1, r - 1, c)
|| dfs(board, word, index + 1, r, c + 1) || dfs(board, word, index + 1, r, c - 1);
// 恢复现场,用于回溯
board[r][c] = temp;
return f;
}
}
}