文章目录
- 单词搜索
- ⛅前言
- 🔒题目
- 🔑题解
单词搜索
⛅前言
大家好,我是知识汲取者,欢迎来到我的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; } } } }
复杂度分析:
- 时间复杂度: n ∗ m ∗ 3 L n*m*3^L n∗m∗3L
- 空间复杂度: O ( n ∗ m ) O(n*m) O(n∗m)
其中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; } } }