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/

相关推荐
WL_Aurora2 小时前
排序算法(二)
java·算法·排序算法
Tisfy2 小时前
LeetCode 2833.距离原点最远的点:计数
算法·leetcode·字符串·题解·模拟·计数
浅念-2 小时前
LeetCode 模拟算法:用「还原过程」搞定编程题的入门钥匙
开发语言·c++·学习·算法·leetcode·职场和发展·模拟
圣保罗的大教堂2 小时前
leetcode 1722. 执行交换操作后的最小汉明距离 中等
leetcode
t-think2 小时前
操作符详解-C语言(下)
c语言·算法
y = xⁿ2 小时前
20天速通LeetCodeday09:关于链表
数据结构·链表
阿Y加油吧2 小时前
算法二刷复盘|旋转排序数组二分双杀(LeetCode 33 & 153)
算法·leetcode·职场和发展
skywalker_112 小时前
力扣hot100(9-找到字符串中所有字母异位词;10-和为K的子数组)
算法·leetcode·职场和发展
无敌昊哥战神2 小时前
【LeetCode 491】递增子序列:不能排序怎么去重?一文讲透“树层去重”魔法!
c语言·c++·python·算法·leetcode