【LeetCode热题100】打卡第24天:单词搜索

单词搜索

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

🔒题目

原题链接:79.单词搜索

image-20230617205049286

🔑题解

  • 解法一:DFS+剪枝

    /**
     * @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 nm3L
    • 空间复杂度: O ( n ∗ m ) O(n*m) O(nm)

    其中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;
            }
        }
    
    }
    
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知识汲取者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值