Python学习笔记——编程练习(1)

本次的python学习进入到编程练习阶段,选取的练习题来源于leetcode

下面是这次选取的练习题:(https://leetcode.com/problems/regular-expression-matching/description/)


Regular Expression Matching

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 letters a-z.
  • p could be empty and contains only lowercase letters a-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

猜你喜欢

转载自blog.csdn.net/ltc8600/article/details/80112928