LeetCode hot100-79.单词搜索

这道题是属于回溯类型的题目。

这里我们们首先创建四个方向上的静态常量数组。

遍历所有格子的行和列,内部通过一个递归函数来查找,满足if条件就是查找到了相应的单词,返回true,否则返回false。

dfs递归函数是如何去做的呢?

先介绍一下参数列表:i是行,j是列,k是word的第k个字母,board就是棋盘上的字母,word就是需要我们查找的字母。

进入dfs后先找到第一个成功的字母,第一个不成功匹配的话直接就返回false了。直到k是word的最后一个字母时,经过第一个if的比对成功,就该返回true了。每访问一个结点的话就把它标记为访问过(也就是将其置为0的操作),避免节点走了回头路。

再通过一个for循环不断变化x,y的值相当于到达一个节点之后在四个方向上移动它去比较。if判断x,y的值一定是在合法的区间内,当前字母找到之后再让k+1去寻找下一个节点。

当前节点没找到的话,以为我们已经将其置为0了,必须要恢复现场。

DFS 是尝试所有可能路径的:

  • 你从 A 出发走了一条路,发现走不通
  • 你必须退回来,把 A 恢复成原来的字符
  • 不然其他路径想经过 A 时,会发现 A 是 0,就误以为不能走了
java 复制代码
class Solution {
    private static final int[][] DIRS = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};

    public boolean exist(char[][] board, String word) {
        char[] w = word.toCharArray();
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (dfs(i, j, 0, board, w)) {
                    return true; // 搜到了!
                }
            }
        }
        return false; // 没搜到
    }

    private boolean dfs(int i, int j, int k, char[][] board, char[] word) {
        if (board[i][j] != word[k]) { // 匹配失败
            return false;
        }
        if (k == word.length - 1) { // 匹配成功!
            return true;
        }
        board[i][j] = 0; // 标记访问过
        for (int[] d : DIRS) {
            int x = i + d[0];
            int y = j + d[1]; // 相邻格子
            if (0 <= x && x < board.length && 0 <= y && y < board[x].length && dfs(x, y, k + 1, board, word)) {
                return true; // 搜到了!
            }
        }
        board[i][j] = word[k]; // 恢复现场
        return false; // 没搜到
    }
}

优化点:假设我们要找的word里面有两个字母C,但是board里面只有一个C,那么我们就不需要再遍历了,可以直接返回false.

并且

如果 word=abcd 但 board 中的 a 很多,d 很少(比如只有一个),那么从 d 开始搜索,能更快地找到答案。(即使我们肉眼去找,这种方法也是更快的)

设 word 的第一个字母在 board 中出现了 x 次,word 的最后一个字母在 board 中出现了 y 次。

如果 y<x,我们可以把 word 反转,相当于从 word 的最后一个字母开始搜索,这样更容易在一开始就满足 boardij != wordk,不会往下递归,递归的总次数更少。

优化后的代码如下:

java 复制代码
class Solution {
    private static final int[][] DIRS = {{0,-1},{0,1},{-1,0},{1,0}};
    public boolean exist(char[][] board, String word) {
        int[] cnt = new int[128];
        for(char[] row : board){
            for(char c : row){
                cnt[c] ++;
            }
        }
        char[] w = word.toCharArray();
        int[] wordCnt = new int[128];
       //优化点一 判断个数
        for(char c : w){
            if(++wordCnt[c] > cnt[c]){
                return false;
            }
        }
        //优化点二 看word开头字母出现的次数多还是结尾字母,结尾多直接反转word
        if(cnt[w[w.length-1]] < cnt[0]){
            w = new StringBuilder(word).reverse().toString().toCharArray();
        }
        for(int i =0;i < board.length;i++){
            for(int j = 0;j < board[i].length; j++){
                if(dfs(i,j,0,board,w)){
                    return true;
                }
            }
        }
        return false;
        
    }
    private boolean dfs(int i, int j, int k, char[][] board, char[] word){
        if(board[i][j] != word[k]){
            return false;
        }
        if(k == word.length -1){
            return true;
        }
        board[i][j] = 0;
        for(int[] d :DIRS){
            int x = i + d[0];
            int y = j + d[1];
            if(0<= x && x < board.length && 0<= y && y < board[x].length && dfs(x,y,k+1,board,word)){
                   return true;
            }
        }
         board[i][j] = word[k];
         return false;
    }
}

参考:

作者:灵茶山艾府

链接:https://leetcode.cn/problems/word-search/solutions/2927294/liang-ge-you-hua-rang-dai-ma-ji-bai-jie-g3mmm/

相关推荐
To_OC5 小时前
LC 131 分割回文串:刚学回溯时,我连怎么切字符串都想不明白
javascript·算法·leetcode
旖-旎6 小时前
LeetCode 518:零钱兑换||(完全背包)—— 题解
c++·算法·leetcode·动态规划·背包问题
To_OC7 小时前
LC 42 接雨水:暴力超时卡半天?前后缀数组一用就通了
javascript·算法·leetcode
delishcomcn8 小时前
AI视觉识别+分切算法:电化铝缺陷检测与裁切一体化解锁
人工智能·算法
触底反弹8 小时前
深入理解大模型采样:Temperature、Top-K、Top-P 的原理与实战
人工智能·算法·面试
雪碧聊技术8 小时前
力扣 LCR 091. 粉刷房子 —— 动态规划入门详解
算法·动态规划
延凡科技11 小时前
多场景落地复盘:端边云架构无人机智能巡检系统设计与实践
大数据·数据结构·人工智能·科技·架构·无人机·能源
CV-Climber11 小时前
检索技术的实际应用
人工智能·算法
hhzz12 小时前
Tiger AI Platform平台中增加人脸识别功能
图像处理·人工智能·算法·计算机视觉·大模型