本次的python学习进入到编程练习阶段,选取的练习题来源于leetcode。
下面是这次选取的练习题:(https://leetcode.com/problems/regular-expression-matching/description/)
Given an input string (s
) and a pattern (p
), implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).
Note:
s
could be empty and contains only lowercase lettersa-z
.p
could be empty and contains only lowercase lettersa-z
, and characters like.
or*
.
Example 1:
Input: s = "aa" p = "a" Output: false Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa" p = "a*" Output: true Explanation: '*' means zero or more of the precedeng element, 'a'. Therefore, by repeating 'a' once, it becomes "aa".
Example 3:
Input: s = "ab" p = ".*" Output: true Explanation: ".*" means "zero or more (*) of any character (.)".
Example 4:
Input: s = "aab" p = "c*a*b" Output: true Explanation: c can be repeated 0 times, a can be repeated 1 time. Therefore it matches "aab".
Example 5:
Input: s = "mississippi" p = "mis*is*p*." Output: false
这道题目比较长,简单来说就是一个表达式的匹配问题。
输入为两个字符串,一个由纯字母组成,一个由字母和“.”,“*”组成。“.”可以匹配任意字母,“*”表示前面的字符可以匹配任意次数,例如“abc”可由“.*“->“…”匹配。
我的解决方式是用递归实现的。将字符串看作两个队列,对队头元素进行匹配,匹配完成后出列,对后面的字符继续递归处理。若出现“*”导致不能简单判断匹配情况,则对后面的字符串进行递归匹配,在匹配不成功的情况下对“*”代表的值递增,直至匹配成功或者匹配失败。
由于在算法执行的过程中调用了很多次递归函数,导致在表达式比较复杂的情况下时间复杂度非常之高。以下是代码实现:
def digui(s,p): if (len(s)==0 and len(p)==0): return True #队列为空时匹配成功 elif (len(s)==0 or len(p)==0): if len(s)==0: if len(p)>=2 and p[1]=="*": return digui(s,p[2:]) #讨论空字符串匹配“字符*”的情况 return False else: if s[0]==p[0] and len(p)>1: #讨论字母匹配的情况 if p[1]=='*' and len(p)>2: #若接“*” s0=s while(1): #迭代并递归对“字母*”后的表达式匹配,决定“*”的匹配值 stop=digui(s0,p[2:]) if stop: return True #匹配成功 s0=s0[1:] if s0=='': return digui(s0,p[2:]) if s0[0]!=p[0]: #“字母*”不适用时退出递归 p=p[2:] break return digui(s0,p) #退出递归后继续匹配 elif p[1]=='*' and len(p)==2: return digui(s+'a',p+'a') #为方便起见,以“字母*”结尾的情况在尾部加上一个字符再作匹配 else: return digui(s[1:],p[1:]) elif p[0]=='.' and len(p)>1: #讨论“.”出现的情况 if p[1]=='*' and len(p)==2: return True #“.*”匹配一切 elif p[1]=='*': s0=s while(len(s0)>=0): stop=digui(s0,p[2:]) if stop: return True if len(s0)==0: break s0=s0[1:] return False else: return digui(s[1:],p[1:]) elif s[0]==p[0] or p[0]=='.': return digui(s[1:],p[1:]) elif s[0]!=p[0] and len(p)>1: #讨论字母不匹配的情况 if p[1]!='*': return False elif p[1]=='*' and len(p)==2: return False else: return digui(s,p[2:]) #若接“*”,则“*”取0继续匹配 else: return False class Solution: def isMatch(self, s, p): return digui(s,p)
测试通过
可见时间复杂度非常高
从该题目的discussion可以看出,较为优秀的解决方法用到了动态规划,由于没有学到动态规划的算法思想,因此需要了解学习一下。
2018/4/27