Leetcode1-100: 44. Wildcard Matching

问题描述

在这里插入图片描述
题目要求: 实现text和pattern的匹配功能,输出true和false

解题思路

这一题跟第10题(Regular Expression Matching)很像,但是加上了'?',去掉了'.'
跟那一题很像,不过用backtrack的话一直通不过说超时,暂时只用了dp和迭代来做。其中dp可以优化一下,具体内容见代码。

implement 1

使用dp来做,dp[i][j]代表s.substring(i)和p.substring(j)的匹配结果,那么每次迭代会出现三个情况:
1. i和j代表的元素匹配上,或者pattern中j对应的字符是'?'的话直接匹配即可
例如: s = “abcde” p = “abc?e”,那么dp[i][j] = dp[i-1][j-1]
2. 没有匹配上但是pattern中遇到了*
例如: s = “abcde” p = “abc*e”,
第四个元素的位置,可以有两种情况,
一种是"*"匹配了空串,这样对应的结果就是dp[i][j] = dp[i-1][j]
另一种是"*"匹配了任意串,这样对应的结果就是dp[i][j] = dp[i][j-1]
3. 没有匹配上并且没有任何特殊符号
直接dp[i][j] = false即可

implement 2

对于dp算法,可以优化一下空间使用,因为每次更新dp[i][j]的时候只需要用到dp[i-1][j-1],dp[i][j-1],dp[i-1][j]三个数,所以可以优化一下空间使用,不再使用dp[s.length()][p.length()]而是用dp[2][p.length()]即可。

implement 3

直接迭代即可,用两个指针指着s和p的对应位置,每次读取指向的字符:
1. 指针对应的位置匹配上或者pattern中出现了"?",这样直接s和p指针都往后一个位置即可
2. 不匹配并且没有读取到的时候p回到star前面的位置并且匹配一个字符,即ss++,同时更新track的值
3. 当读取到一个
的时候,记录star,track的位置,然后更新pp表示*匹配一个空串
4. 如果上述情况都没出现,直接返回false

代码实现

implement 1

public boolean isMatch(String s, String p) {
	//1. dynamic programming
        //dp[i][j]: isMatch(s.substring(0, i+1), p.substring(0, j+1))
        boolean[][] dp = new boolean[s.length()+1][p.length()+1];
        dp[0][0] = true;
        for(int i = 1; i < p.length()+1; i++)
            dp[0][i] = dp[0][i-1] && (p.charAt(i-1) == '*');
        for(int i = 1; i < s.length(); i++)
            dp[i][0] = false;
        for(int i = 1; i < s.length()+1; i++)
            for(int j = 1; j < p.length()+1; j++) {
                //当i,j对应的字符相同或者j对应的是'?'的时候说明匹配成功,只需要看前面的情况即可
                if(s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '?')
                    dp[i][j] = dp[i-1][j-1];
                //当j对应的字符是'*'说明可以匹配任意串或者空串,若是任意则等于dp[i][j-1],若是空则等于dp[i-1][j]
                else if(p.charAt(j-1) == '*')
                    dp[i][j] = dp[i-1][j] || dp[i][j-1];
                else
                    dp[i][j] = false;
            }
        return dp[s.length()][p.length()];
}

在这里插入图片描述
复杂度分析:

时间复杂度: O(n2)
空间复杂度: O(1)

implement 2

public boolean isMatch(String s, String p) {
	// 2. dynamic programming 空间优化: 由于计算dp[i][j]只用dp[i-1][j-1], dp[i][j-1], dp[i-1][j], 所以只需要存储两行元素即可完成dp(即当前行和上一行)
        boolean[][] dp = new boolean[2][p.length()+1];
        dp[0][0] = true;
        for(int i = 1; i < p.length()+1; i++)
            dp[0][i] = dp[0][i-1] && (p.charAt(i-1) == '*');
        for(int i = 1; i < s.length()+1; i++) {
            dp[i%2][0] = false;
            for(int j = 1; j < p.length()+1; j++) {
                //当i,j对应的字符相同或者j对应的是'?'的时候说明匹配成功,只需要看前面的情况即可
                if(s.charAt(i-1) == p.charAt(j-1) || p.charAt(j-1) == '?')
                    dp[i%2][j] = dp[(i-1)%2][j-1];
                //当j对应的字符是'*'说明可以匹配任意串或者空串,若是任意则等于dp[i][j-1],若是空则等于dp[i-1][j]
                else if(p.charAt(j-1) == '*')
                    dp[i%2][j] = dp[(i-1)%2][j] || dp[i%2][j-1];
                else
                    dp[i%2][j] = false;
            }
        }
        return dp[s.length()%2][p.length()]; 
}

在这里插入图片描述
可以看出来,空间效率高了很多

复杂度分析:

时间复杂度: O(n2)
空间复杂度: O(1)

implement 3

public boolean isMatch(String s, String p) {
	//3. 迭代,并用两个指针指向两个串要匹配的元素
        int ss = 0, pp = 0;
        int star = -1, track = 0;
        while(ss < s.length()) {
            if(pp < p.length() && (s.charAt(ss) == p.charAt(pp)||p.charAt(pp) == '?')) {
                ss++;
                pp++;
            } else if(pp < p.length() && p.charAt(pp) == '*') {
                //当读取到一个*的时候,记录star,track的位置,然后更新pp表示*匹配一个空串
                star = pp;
                track = ss;
                pp++;
            } else if(star != -1) {
                //不匹配并且没有读取到*的时候p回到star前面的位置并且匹配一个字符,即ss++,同时更新track的值
                track++;
                ss = track;
                pp = star+1;
            }
            else
                return false;  
                        
        }
        while(pp < p.length() && p.charAt(pp) == '*')
            pp++;
        return pp == p.length();
}

在这里插入图片描述
复杂度分析:

时间复杂度: O(mn) ,m,n代表s和p的长度
空间复杂度: O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值