剑指Offer(五十二):正则表达式匹配(Java版)

描述

请实现一个函数用来匹配包括'.'和'*'的正则表达式。模式中的字符'.'表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"ab*ac*a"匹配,但是与"aa.a"和"ab*a"均不匹配

数据范围:

1.str 可能为空,且只包含从 a-z 的小写字母。

2.pattern 可能为空,且只包含从 a-z 的小写字母以及字符 . 和 *,无连续的 '*'。

3.1 <= str.length <= 20

4.1 <= pattern.length <= 30

要求:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)

示例1

输入:

"aaa","a*a"

返回值:true

说明:

中间的*可以出现任意次的a,所以可以出现1次a,能匹配上

示例2

输入:

"aad","c*a*d"

返回值:true

说明:

因为这里 c 为 0 个,a被重复一次, * 表示零个或多个a。因此可以匹配字符串 "aad"。

示例3

输入:

"",".*"

返回值:true

说明:

".*" 表示可匹配零个或多个('*')任意字符('.')

示例4

输入:

"aaab","a*a*a*c"

返回值:false

解法

这道题看起来有点小复杂,但是其核心在于‘.’和‘*’,对于‘.’来说,它可以和任意字符都匹配,当做任意一个普通字符,而对于‘*’来说,我们得分情况来进行讨论,我们把所有情况捋清楚以后,就可以写代码了

在每轮的匹配中,如果pattern的第二个字符是‘*’

  1. 第一个字符不匹配('.'与任意字符视作匹配),那么'*'只能代表匹配0次,比如'ba'与'a*ba',字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式

  2. 第一个字符匹配,那么'*'可能代表匹配0次,1次,多次,比如'aaa'与'a*aaa'、'aba'与'a*ba'、'aaaba'与'a*ba'。匹配0次时,字符串不变,模式向后移动两个字符,然后匹配剩余字符串和模式;匹配1次时,字符串往后移动一个字符,模式向后移动2个字符;匹配多次时,字符串往后移动一个字符,模式不变;

而当Patttern第二个字符不是'*'时,情况就简单多了:

  1. 如果字符串的第一个字符和模式中的第一个字符匹配,那么在字符串和模式上都向后移动一个字符,然后匹配剩余字符串和模式。

  2. 如果字符串的第一个字符和模式中的第一个字符不匹配,那么直接返回false。

完整代码如下

public boolean match (String str, String pattern) {
        if(null == str || null == pattern){
            return false;
        }
        return matchPattern(str,0,pattern,0);
    }

    private boolean matchPattern(String str,int lengthStr,String pattern , int lengthPattern){
        //说明都到了最后一位
        if((lengthStr == str.length()) && (lengthPattern == pattern.length())){
            return true;
        }
        if((lengthStr != str.length()) && (lengthPattern == pattern.length())){
            return false;
        }
        //判断pattern下一位是否为*
        //防止越界
        if(lengthPattern+1 < pattern.length() && pattern.charAt(lengthPattern+1) == '*'){
            if(lengthStr != str.length() && ((str.charAt(lengthStr) == pattern.charAt(lengthPattern))|| (pattern.charAt(lengthPattern)=='.'))){
                return matchPattern(str,lengthStr+1,pattern,lengthPattern) || matchPattern(str,lengthStr+1,pattern,lengthPattern+2) || matchPattern(str,lengthStr,pattern,lengthPattern+2) ;
            }else {
                return matchPattern(str,lengthStr,pattern,lengthPattern+2);
            }
        }
        if((lengthStr != str.length() && str.charAt(lengthStr) == pattern.charAt(lengthPattern)) || (lengthStr != str.length() && pattern.charAt(lengthPattern) == '.')){
            return matchPattern(str,lengthStr+1,pattern,lengthPattern+1);
        }
        return false;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值