| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> LeetCode10-正则表达式匹配(递归) -> 正文阅读 |
|
[数据结构与算法]LeetCode10-正则表达式匹配(递归) |
题目背景给你一个字符串?
所谓匹配,是要涵盖 整个?字符串? 编程前一道典型的动态规划或者递归的算法题,难度是hard,无论是dp还是递归,思路都差不多:找到转移方程(是的,递归也需要找转移方程,如何降到小规模的问题),本文章采取递归的方法,为了避免堆栈溢出,加了cache 编程中编程伊始:边界检查一开始比较简单,做条件判断和边界检查
需要注意的是,当s为空的时候,p可以是空,也可以是任意字符和*的组合,其实 【任意字符和*的组合可以匹配空】这件事是很容易被忽略的 编程核心:转移方程递归里面也有类似转移方程的概念,一个大规模的问题,想用一个小规模的问题去解,该怎么办呢,就需要找到小规模问题和大规模问题之间的联系,这种联系在动态规划里面就是转移方程,因为这里涉及两个变量,所以很明显,这里的【小规模】也有很多种【解释】(至少需要两种解释)
因为我们的【边界条件】是相等,或者一种为空,或者另一种为空,总共三种情况,又因为在递归的场景下,需要让情况【坍缩】到某一个【边界条件】中,所以在找【小规模问题】的时候,就必须使得:
最好的情况一般是(s[:-1], p) 和(s, p[:-1]),但往往这种组合在题目中没有实际意义,或者无法覆盖全部情况。所以第一步我就找到了这两种的组合(有没有其他找【小规模问题】的方法呢,这里挖一个坑,在文章的【总结】部分解决,不过瘾的同学也可以直接去【总结】看答案,但是强烈建议大家跟着文章的思路走)此时代码如下(注意用到了范围,就一定要判断长度是否够)
编程完善:分类讨论如果是第一种情况:self.isMatch(s[:-1],?p[:-1]),意味着在已经match的情况下,s和p都要再加一个字符,很容易想到两种可能
此时有个问题,如果p追加的字符是"*",有没有可能让这种情况成立呢?这里再挖一个坑,同样在总结的时候说,不过瘾的同学,可以直接跳到【总结】)。 如果是第二种情况:self.isMatch(s[:-1],?p),意味着在已经match的情况下,s要再加一个字符,这时p很不爽,如果只有s强行追加,p的最后就一定是一个超能力的字符来兜底,就是"*",因为"."是没有能力延长匹配的,然而字符"*"相当于一个辅助的字符,能否帮上忙完全看前面的字符,所以就要求"*"前面的字符给力一点,
将第二种情况的分析总结起来就是:
此时代码如下,注意在用到下标的时候,一定要判断越界的情况
编程之禅:Debug当我满心欢喜的开始调试的时候,发现 "aa"和"a*"就匹配不过去,debug思路如下 s="aa"; p="a*"
然而【a*可以匹配空】这一条规则,在我的代码中并没有体现,于是我一开始把它放到了开头,就像这样
但是还没有提交,我就找了一个测试用例,s="b";?p="ba*",果然没有通过,原因在于,如果把【a*可以匹配空】这件事用边界条件来表达,这就说明,需要一步一步去掉最后的字符【坍缩】到这个状态才能生效,而如果无法【坍缩】到最后这一步,比如p="ba*",无论怎么从后面删减,也无法得到"a*"(总会有一个b),所以,应该再加一个转移方程。最终的代码就像这样:
总结关于题目的部分就到这里了,现在解决文章中埋下的坑,以及我对这道题目的思考 1. 如何寻找小规模的问题 这里我给出两个思路,第一个比较好想,一般就是-1,-2这种,在只有一个变量的时候,比较简单,基本有一个就行。但在有两种变量的情况下,转移方程一定至少有两个,需要保证在所有情况下都能让情况【坍缩】到【边界条件】,在思考每种情况下成立的条件时,需要【尽可能的考虑题目中给出的条件】。另一个思路就是反过来想问题,将题目中给出能成立的可能拆解成条件。比如这道题,如果最后再审视完成的代码,可以清楚的看到,我们拆解出来的这三个【小规模问题】分别代表了题目中 . 和 * 的三种功能:
总结建议:拿到题目进行分析后,尽量用思路2,梳理题目中成立的条件来整理转移方程,在尝试的时候可以用思路1,试着让规模-1,-2,然后利用题干中的条件让情况成立。 2. 在某一种情况下是否需要将所有条件写全 细心的读者可能发现了,这个代码中很多地方似乎并没有写全,比如在边界条件中,【*可以代表空】这个事情并没有写到边界条件中,再比如第二种情况,s和p都要加一个字符的时候,如果p的最后一个字符是*,是否也有可能成立呢? 其实是的,多测试几次你就会发现,上述几种情况写不写都无关紧要,重要的是我们已经把【题目中表达的几种成立的可能性通过小规模问题表达出来了】这件事,至于是在哪里表达的,似乎并不重要,这也是【递归】神奇的地方吧,只要我写了,总会掉到那里去 课后作业给看到这里的同学一个大大的赞,最后留下一个小思考题,按照【总结】所说,尽量的按照题目中成立的可能设置【小规模问题】,那".*"可以匹配任意字符,这种特殊组合为什么没有成为小规模问题中的一个,或是出现在边界条件中呢? |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/25 16:50:42- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |