当前位置: 首页 > article >正文

leetcode79:单词搜索

原题地址:79. 单词搜索 - 力扣(LeetCode)

题目描述

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE"
输出:true

示例 3:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB"
输出:false

解题思路

本问题可以使用回溯算法来实现,具体步骤如下:

  1. 遍历网格的每一个位置,从该位置开始尝试构建 word
  2. 如果当前位置的字符与 word 中当前的字符匹配,则尝试从当前位置出发继续匹配 word 的下一个字符。
  3. 使用 visited 数组标记当前位置,防止重复访问。
  4. 如果可以从当前位置匹配出完整的 word,返回 true,否则回溯。
  5. 通过回溯算法遍历所有可能的路径,直到找到一个有效路径

源码实现

class Solution {
    public boolean exist(char[][] board, String word) {
        // 获取网格的行数和列数
        int h = board.length, w = board[0].length;
        // 记录访问过的网格位置,防止重复访问
        boolean[][] visited = new boolean[h][w];
        
        // 遍历整个网格,尝试从每个位置出发查找单词
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                // 如果从当前网格位置能够找到完整的单词,返回 true
                boolean flag = check(board, visited, i, j, word, 0);
                if (flag) {
                    return true;
                }
            }
        }
        // 如果遍历结束都没有找到单词,返回 false
        return false;
    }

    // 使用回溯算法检查从 board[i][j] 开始是否能找到从 word[k] 开始的单词
    public boolean check(char[][] board, boolean[][] visited, int i, int j, String s, int k) {
        // 如果当前格子的字符不等于 word[k],返回 false
        if (board[i][j] != s.charAt(k)) {
            return false;
        } 
        // 如果已经匹配到 word 的最后一个字符,返回 true
        else if (k == s.length() - 1) {
            return true;
        }

        // 标记当前位置已访问
        visited[i][j] = true;

        // 定义四个方向的移动:右、左、下、上
        int[][] directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        boolean result = false;

        // 遍历四个方向,继续查找
        for (int[] dir : directions) {
            int newi = i + dir[0], newj = j + dir[1];
            // 检查新位置是否在网格内
            if (newi >= 0 && newi < board.length && newj >= 0 && newj < board[0].length) {
                // 如果新位置未被访问过,递归查找
                if (!visited[newi][newj]) {
                    boolean flag = check(board, visited, newi, newj, s, k + 1);
                    if (flag) {
                        result = true;
                        break; // 如果找到有效路径,提前结束循环
                    }
                }
            }
        }

        // 回溯,标记当前位置为未访问
        visited[i][j] = false;
        return result; // 返回是否找到有效路径
    }
}

复杂度分析

  1. 时间复杂度

    • 最坏情况下,回溯算法会遍历每一个可能的路径,对于每个单元格,都可能尝试四个方向进行递归查找,直到所有字符都被遍历。
    • 假设网格的大小为 m x n,字符串的长度为 L,那么在最坏情况下,算法的时间复杂度是:O(m * n * 4^L)
      • m * n:遍历所有的起始位置。
      • 4^L:对于每个位置,最多递归 L 层,每一层有四个方向可以选择。
  2. 空间复杂度

    • 回溯算法的递归深度最多为 L,因此栈的空间复杂度为 O(L)
    • 另外,我们使用了一个大小为 m x n 的 visited 数组,用来标记是否访问过某个位置。因此,空间复杂度为 O(m * n)

http://www.kler.cn/a/450682.html

相关文章:

  • 使用 perf 工具进行性能分析
  • Linux程序设计(第四版)| 学习笔记
  • vue3标签中的ref属性如何使用$refs获取元素
  • 详解磁盘IO、网络IO、零拷贝IO、BIO、NIO、AIO、IO多路复用(select、poll、epoll)
  • ECharts散点图-气泡图,附视频讲解与代码下载
  • 华为浏览器(HuaweiBrowser),简约高效上网更轻松
  • http的访问过程或者访问页面会发生什么
  • 【国产NI替代】基于FPGA的4通道电压 250M采样终端边缘计算采集板卡,主控支持龙芯/飞腾
  • C# OpenCV机器视觉:缺陷检测
  • Web前端基础知识(一)
  • myexcel的使用
  • workman服务端开发模式-应用开发-vue-element-admin挂载websocket
  • Log4j2漏洞复现
  • 使用git管理项目版本
  • 基于Liveweb地铁轨道交通视频监控综合管理系统方案
  • 【ROS2】坐标TF发布(静态)
  • 支付域——支付路由设计
  • Flutter组合动画学习
  • Linux系统编程深度解析:C语言实战指南
  • 了解RPC
  • 《Web 应用项目开发:从构思到上线的全过程》
  • UE5 渲染管线 学习笔记
  • 全国硕士研究生入学考试(考研)考研时间线之大三
  • 如何获取 ABAP 内表中的重复项
  • springboot容器无法获取@Autowired对象,报null对象空指针问题的解决方式
  • VSCode+WSL作为IDE开发和管理深度学习项目