欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 【Leetcode 热题 100】79. 单词搜索

【Leetcode 热题 100】79. 单词搜索

2025/6/4 22:12:01 来源:https://blog.csdn.net/2401_88859777/article/details/144860975  浏览:    关键词:【Leetcode 热题 100】79. 单词搜索

问题背景

给定一个 m × n m \times n m×n 二维字符网格 b o a r d board board 和一个字符串单词 w o r d word word。如果 w o r d word word 存在于网格中,返回 t r u e true true;否则,返回 f a l s e false false
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

数据约束

  • m = b o a r d . l e n g t h m = board.length m=board.length
  • n = b o a r d [ i ] . l e n g t h n = board[i].length n=board[i].length
  • 1 ≤ m , n ≤ 6 1 \le m, n \le 6 1m,n6
  • 1 ≤ w o r d . l e n g t h ≤ 15 1 \le word.length \le 15 1word.length15
  • b o a r d board board w o r d word word 仅由大小写英文字母组成

解题过程

这题放在了回溯这个类别下,其实更适合当作图的深度优先遍历相关问题来解决,可以参考模板题 岛屿数量。
一般做法的框架是定义四个方向,对图中每个节点都尝试搜索它的相邻节点,在不越界且并且和字符串相应位置的字符相同时,进一步递归检查。
有两个可以优化的地方。
一是通过遍历搭配哈希表来统计图中和字符串中每种字符出现的次数,一旦发现字符串中所要求的某种字符出现的次数大于图中对应字符出现的次数,就不可能满足条件,可以避免深搜,直接返回结果。
这样做的时间消耗是 O ( N 2 ) O(N ^ 2) O(N2),要比暴力搜索的指数级好得多。
在此基础上,考虑到返回 f a l s e false false 的情况是某个字符处不匹配造成的,并且遍历字符串的顺序对结果没有影响可以比较字符串中第一个字符和最后一个字符出现的次数,从要求比较高的那一头开始搜索,这样更容易出现不满足条件返回的情形,可以有效减少递归搜索的次数。

具体实现

class Solution {private static final int[][] DIRECTIONS = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};public boolean exist(char[][] board, String word) {// 统计图中每种字符出现的次数int[] count = new int[128];for(char[] row : board) {for(char c : row) {count[c]++;}}// 优化一,统计字符串中每种字符要求的次数,如果大于图中出现的相应字符数,直接返回 falsechar[] chW = word.toCharArray();int[] wordCount = new int[128];for(char c : chW) {if(++wordCount[c] > count[c]) {return false;}}// 优化二,颠倒单词顺序不影响结果,从出现次数多的那头开始搜索if(count[chW[chW.length - 1]] < count[chW[0]]) {chW = new StringBuilder(word).reverse().toString().toCharArray();}// 常规框架,对图中的每个字符位置都尝试进行搜索for(int i = 0; i < board.length; i++) {for(int j = 0; j < board[0].length; j++) {if(dfs(i, j, 0, board, chW)) {return true;}}}return false;}private boolean dfs(int x, int y, int i, char[][] board, char[] word) {if(board[x][y] != word[i]) {return false;}// 注意,执行到这里的时候已经判断了图中当前字符和字符串对应位置的字符相同,到达了边界if(i == word.length - 1) {return true;}// 修改图,用来标记已访问过board[x][y] = 0;for(int[] direction : DIRECTIONS) {int nextX = x + direction[0];int nextY = y + direction[1];// 只有在不越界且进一步递归也返回 true 的情况下,当前位置才能返回 trueif(0 <= nextX && nextX < board.length && 0 <= nextY && nextY < board[0].length && dfs(nextX, nextY, i + 1, board, word)) {return true;}}// 恢复现场board[x][y] = word[i];return false;}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词