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 的最后一个字母开始搜索,这样更容易在一开始就满足 board[i][j] != word[k],不会往下递归,递归的总次数更少。

优化后的代码如下:

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/

相关推荐
浅念-5 小时前
递归解题指南:LeetCode经典题全解析
数据结构·算法·leetcode·职场和发展·排序算法·深度优先·递归
Kiling_07045 小时前
Java集合进阶:Set与Collections详解
算法·哈希算法
智者知已应修善业5 小时前
【51单片机89C51及74LS273、74LS244组成】2022-5-28
c++·经验分享·笔记·算法·51单片机
洛水水6 小时前
【力扣100题】33.验证二叉搜索树
算法·leetcode·职场和发展
SimpleLearingAI6 小时前
聚类算法详解
算法·数据挖掘·聚类
刀法如飞7 小时前
Go 字符串查找的 20 种实现方式,用不同思路解决问题
算法·面试·程序员
Dlrb12119 小时前
C语言-指针数组与数组指针
c语言·数据结构·算法·指针·数组指针·指针数组·二级指针
WL_Aurora9 小时前
Python 算法基础篇之集合
python·算法
平行侠9 小时前
A15 工业路由器IP前缀高速检索与内存压缩系统
网络·tcp/ip·算法
阿旭超级学得完10 小时前
C++11包装器(function和bind)
java·开发语言·c++·算法·哈希算法·散列表