剑指Offer 12—矩阵中的路径

2023-11-19

题目描述

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

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

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

题目直达

力扣https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof/

解题思路

本问题是典型的矩阵搜索问题,可使用 深度优先搜索(DFS)+ 剪枝 解决。

  • 深度优先搜索: 可以理解为暴力法遍历矩阵中所有字符串可能性。DFS 通过递归先朝一个方向搜到底再回溯至上个节点,沿另一个方向搜索,以此类推。
  • 剪枝: 在搜索中,遇到 这条路不可能和目标字符串匹配成功 的情况(例如:此矩阵元素和目标字符不同、此元素已被访问),则应立即返回,称之为 可行性剪枝 。


DFS解析:

  • 递归参数: 当前元素在矩阵 board 中的行列索引 i 和 j ,当前目标字符在 word 中的索引 k 。
  • 终止条件:
    • 返回False:行或列索引越界、当前矩阵元素与目标字符不同 、当前矩阵元素已访问过
    • 返回True:k = len(word) - 1 ,即字符串 word 已全部匹配。

递推工作:

  1. 标记当前矩阵元素: 将 board[i][j] 修改为 空字符 '' ,代表此元素已访问过,防止之后搜索时重复访问。
  2. 搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需找到一条可行路径就直接返回,不再做后续 DFS ),并记录结果至 res 。

  3. 还原当前矩阵元素: 将 board[i][j] 元素还原至初始值,即 word[k] 。

 返回值:返回布尔量 res ,代表是否搜索到目标字符串。

 使用空字符(Python: '' , Java/C++: '\0' )做标记是为了防止标记字符与矩阵原有字符重复。当存在重复时,此算法会将矩阵原有字符认作标记字符,从而出现错误。

 算法流程

C++代码实现

class Solution 
{
public:
    bool exist(vector<vector<char>>& board, string word) 
    {
        rows = board.size();	//字符矩阵的行数(0~rows-1)
        cols = board[0].size();	//字符矩阵的列数(0~cols-1)
        for(int i = 0; i < rows; i++) 
        {
            for(int j = 0; j < cols; j++) 
            {
                //当前元素在矩阵 board 中的行列索引 i 和 j
                //当前目标字符在 word 中的索引 k
                //从字符矩阵的左上角开始寻找,从上往下开始,看这个位置的矩阵元素是否是字符单词中的第一个字符
                if(dfs(board, word, i, j, 0)) 
                    return true;
            }
        }
        //遍历完了整个矩阵元素,依然没有找到一条合适的路,返回false
        return false;
    }
private:
    int rows, cols;
    bool dfs(vector<vector<char>>& board, string word, int i, int j, int k) 
    {
        //如果索引越界了,或者是当前位置的矩阵元素不等于目标匹配字符,返回false
        if(i >= rows || i < 0 || j >= cols || j < 0 || board[i][j] != word[k]) 
            return false;
        
        //能够到达这一步,证明索引没有越界,且当前位置在矩阵中的元素等于目标匹配字符
        //所以如果目标字符的索引为最后一个了,那肯定匹配成功了,直接返回true
        if(k == word.size() - 1) 
            return true;
        
        //标记当前矩阵元素,代表此元素已访问过,防止之后搜索时重复访问。
        //因为如果向下递归时,下一层递归会往上走,这样是为了防止走回头路
        board[i][j] = '\0';
        
        //对下一个待匹配字符进行搜索其余路径(下,上,右,左)
        //只要有一个返回true就不会继续往下试探了
        bool res = dfs(board, word, i + 1, j, k + 1) || dfs(board, word, i - 1, j, k + 1) || 
                      dfs(board, word, i, j + 1, k + 1) || dfs(board, word, i , j - 1, k + 1);
        
       
/*
递归搜索匹配字符串过程中,需要 board[i][j] = '\0' 来防止 ”走回头路“ 。当匹配字符串不成功时,会回溯返回,此时需要board[i][j] = word[k] 来 取消对此单元格的标记。 在DFS过程中,每个单元格会多次被访问的, board[i][j] = '\0'只是要保证在当前匹配方案中不要走回头路。
取消对board[i][j]的标记是因为只代表此次搜索过程中,该元素已访问过,
当初始i j变化时,又开始了另一次搜索过程
*/
        board[i][j] = word[k]; //还原当前矩阵元素,因为如果当前的节点不满足路径要求,需要撤回到上一个节点,然而上一个节点此时已经赋值为“\0”,需要还原一下,继续探索其它路径。
        return res;
    }
};

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

剑指Offer 12—矩阵中的路径 的相关文章

  • 这一次,我顿悟了

    大家好 我是苍何 昨晚和编程导航 星球嘉宾也是我的引路人闫 y n 小林大佬 畅聊了 4 个 小时 至今内心还是久久不能平静 小林和我一样是跨界转行 他是医学院毕业 大二开始自学编程 并写博客记录 迄今有 30 万编程学习者关注 毕业后在某

随机推荐

  • OSI七层模型以及各层的作用

    OSI七层模型 OSI七层模型包括 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 具体作用 物理层 主要定义物理设备标准 如网线的接口类型 各种传输介质的传输速率等 主要作用是传输bit流 主要设备 集线器 数据链路层 主要将
  • HMI智能串口屏——在STM32开发板上的实战应用及其详解

    HMI智能串口屏 在STM32开发板上的实战应用及其详解 一 HMI智能串口屏使用步骤 二 附录 一 HMI智能串口屏使用步骤 安装USART HMI软件 一般买的串口屏里面 商家送的资料里面都有改该软件 打开软件 并点击左上角的 新建 选
  • Unique Binary Search Trees -- LeetCode

    原题链接 http oj leetcode com problems unique binary search trees 这道题要求可行的二叉查找树的数量 其实二叉查找树可以任意取根 只要满足中序遍历有序的要求就可以 从处理子问题的角度来
  • 智能制造中的智能制造平台:应用案例介绍

    作者 禅与计算机程序设计艺术 智能制造中的智能制造平台 应用案例介绍 智能制造作为我国大力发展的重要战略 旨在通过改变传统制造业的生产模式 提高制造业的自主创新能力和核心竞争力 智能制造平台作为实现智能制造的核心基础 对于企业来说具有重要的
  • 春秋云镜:CVE-2019-9042(Sitemagic CMS v4.4 任意文件上传漏洞)

    一 题目 靶标介绍 Sitemagic CMS v4 4 index php SMExt SMFiles 存在任意文件上传漏洞 攻击者可上传恶意代码执行系统命令 进入题目 admin admin index php SMExt SMFile
  • .NET Core 下定时任务调度

    一 增加本地json持久化调度任务 无需数据库 1 首先 我们创建一个空白的ASP NET Core 项目 MVC Razor和WebAPI都行 如图 2 通过nuget引用最新版本的GZY Quartz MUI组件 如图 组件的项目地址G
  • hibernate与sqlserver的连接

    Hibernate是一个开放源代码的对象关系映射框架 它对JDBC进行了非常轻量级的对象封装 它将POJO与数据库表建立映射关系 是一个全自动的orm框架 hibernate可以自动生成SQL语句 自动执行 使得Java程序员可以随心所欲的
  • 【MySQL】sql给表起别名

    有时候 在对数据库中的表进行操作的时候 发现表名比较冗长 这时候我们就需要对表创建一个别名 别名的关键字为as 也可以不加 现在有一个student表 结构如下 现在我认为student太长了 我不想一直打 sql语句如下 select a
  • setTimeout异步

    同步任务和异步任务 同步和异步操作的区别就是是否阻碍后续代码的执行 同步任务是那些没有被引擎挂起 在主线程上排队执行的任务 只有前一个任务执行完毕 才能执行后一个任务 异步任务是那些被引擎放在一边 不进入主线程 而进入任务队列的任务 只有引
  • 【IEEE 13 节点分配系统中的THD降低】系统的谐波分析给出了各种总线上电流和电压的谐波频谱和THD(Simulink实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Simulink仿真实现 1 概述 IEEE 13 节点分配系统中的THD
  • 第三方微信登陆的后台实现

    关于微信第三方的开发 官方文档给了很详细的解析说明 有不清楚流程的同学可以先去官网学习 而我这里主要是整理一下自己的后台处理流程 其实微信登录就是通过用户的授权 允许app获取用户的微信信息 再往自己的数据库插入获取的信息 这里用手机app
  • 6. C++知识点之三目运算符

    三目运算符 C 有一个常用来代替if else语句的操作符 这个操作符被称为三木运算符 它是C 中唯一一个需要3个操作数的操作符 该操作符的通用格式如下 b a c 如果b为真 则整个表达式的值为a 否则表达式的值为c 下面两个语句演示了该
  • 千万并发连接下,如何保障网络性能

    点击一键订阅 云荐大咖 专栏 获取官方推荐精品内容 学技术不迷路 过去几十年互联网呈爆发式的增长 内容的丰富以及层出不穷的DDoS攻击等 对网络性能提出了极大的挑战 也同样促进了网络基础设施的快速发展 运营商的带宽越来越大 CPU 网卡等硬
  • Ubuntu /etc/security/limits.conf 不生效

    遇到报错 RuntimeError unable to open shared memory object in read write mode 查到的教程说需要ulimit n 设置一个比较大的数 用ulimit n 发现最大是1024
  • Element组件浅尝辄止5:Empty 空状态组件

    Empty空状态组件 空状态时的占位提示 如第一次进入当前功能模块时 数据状态为空 则展示空状态 可用到Empty组件 1 How
  • 可以向同事学学shader了

    今天无意中和同事聊天 发现他竟然会级联阴影 级联阴影不是新技术 但是我见过的 能用的真少 大多数停留在理论阶段 可能是我遇见的优秀的人不多吧 不管怎样 立足现在公司 多向高手学习
  • 《Effective Modern C++》第0章学习记录

    Acknowledgement C 0x C 11 C 14 Usenet newsgroup comp std c Stack Overflow Overview of the New C Modern C Design Going na
  • SQL语句大全(第21天) (转)

    第一大章 创建数据库 CREATE 创建 DATABASE 数据库 ace 数据库名字 打开数据库 USE 打开 ace 数据库名字 给表格 SHOW 显示 TABLES 所以列表名字 创建表 用户名 id ID user 用户 passw
  • 大数据基础

    1 HDFS 1 HDFS为什么不适合存储大量小文件 答 1 大量文件的元数据占用NameNode大量内存空间 2 磁盘寻道时间超过读取时间 2 HDFS 何时离开安全模式 答 ActiveNameNode启动时HDFS进入安全模式只读 d
  • 剑指Offer 12—矩阵中的路径

    题目描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 如果 word 存在于网格中 返回 true 否则 返回 false 单词必须按照字母顺序 通过相邻的单元格内的字母构成 其中 相邻 单元格是那些水平相邻