NC44:通配符匹配

通配符匹配

http://www.nowcoder.com/practice/e96f1a44d4e44d9ab6289ee080099322

思路1:动态规划

在给定的模式 p 中,只会有三种类型的字符出现:

  • 小写字母 a-z,可以匹配对应的一个小写字母;
  • 问号 ?,可以匹配任意一个小写字母;
  • 星号 *∗,可以匹配任意字符串,可以为空,也就是匹配零或任意多个小写字母
    其中「小写字母」和「问号」的匹配是确定的,而「星号」的匹配是不确定的,因此我们需要枚举所有的匹配情况。为了减少重复枚举,我们可以使用动态规划来解决本题
    图片说明
    图片说明
    public class Solution {
      public boolean isMatch(String s, String p) {
          int slen=s.length();
          int plen=p.length();
          boolean[][] dp=new boolean[slen+1][plen+1];
          dp[0][0]=true;
          for(int j=1;j<=plen;j++){
              if(p.charAt(j-1)=='*'){
                  dp[0][j]=true;
              }
              else{
                  break;
              }
          }
          for(int i=1;i<=slen;i++){
              for(int j=1;j<=plen;j++){
                  if(p.charAt(j-1)=='*'){
                      dp[i][j] = dp[i-1][j] || dp[i][j-1];
                  }
                  else if(s.charAt(i-1)==p.charAt(j-1) || p.charAt(j-1)=='?'){
                      dp[i][j] = dp[i-1][j-1];
                  }
              }
          }
          return dp[slen][plen];
      }
    }

复杂度分析

  • 时间复杂度:O(mn),其中 m 和 n 分别是字符串 s 和模式 p 的长度。
  • 空间复杂度:O(mn),即为存储所有 (m+1)(n+1)个状态需要的空间。此外,在状态转移方程中,由于 dp[i][j] 只会从 dp[i][..] 以及 dp[i−1][..] 转移而来,因此我们可以使用滚动数组对空间进行优化,即用两个长度为 n+1的一维数组代替整个二维数组进行状态转移,空间复杂度为 O(n)。

思路2:贪心

本题难点在于处理星号的匹配,用iStar和jStar表示星号在s和p中匹配的位置,初始值为-1,i和j表示当前匹配的位置,匹配过程如下:

  • 如果s和p中字符匹配,则分别自增i和j
  • 否则如果p中当前字符为星号,则标记iStar和jStar,同时自增j
  • 否则如果iStar >= 0,表示之前匹配过星号,因为星号可以匹配任意字符串,所以继续递增i,同时移动j为jStar下一个字符
  • 否则返回false
  • 当s中字符匹配完,p中字符不能有除星号以外字符
    bool isMatch(string s, string p) {
          int i = 0, j = 0, iStar = -1, jStar = -1, m = s.size(), n = p.size();
          while (i < m) {
              if (j < n && (s[i] == p[j] || p[j] == '?')) {
                  ++i, ++j;//i,j向后瞬移
              } else if (j < n && p[j] == '*') {
              //记录如果之后序列匹配不成功时, i和j需要回溯到的位置
                  iStar = i;//记录星号,*可以匹配空字符
                  jStar = j++;
                  //记录星号 并且j移到下一位 准备下个循环s[i]和p[j]的匹配
              } else if (iStar >= 0) {
                  //发现字符不匹配且没有星号出现 但是istar>0 说明可能是*匹配的字符数量不对 这时回溯
                  i = ++iStar;
                  //i回溯到istar+1 因为上次从s串istar开始对*的尝试匹配已经被证明是不成功的(不然不会落入此分支) 
                  //所以需要从istar+1再开始试 同时inc istar 更新回溯位置
                  j = jStar + 1;
                  //j回溯到jstar+1 重新使用p串*后的部分开始对s串istar
                  //(这个istar在上一行已经inc过了)位置及之后字符的匹配 
              } else return false;
          }
          while (j < n && p[j] == '*') 
               ++j;//去除多余星号
          return j == n;
      }
名企高频面试算法题解 文章被收录于专栏

牛客题霸 - 程序员面试高频题 - 题解

全部评论
销户!
点赞 回复 分享
发布于 2021-08-15 01:06

相关推荐

03-12 09:57
软件测试
程序员小白条:1)确定测试,测开的方向,技术栈不能写这么少 2)课程凑数的,不是99,100分没必要写 3)实习经历这块要有突出的不是劳动性质的亮点,自己设计的什么方案,什么自动化?什么提效工具?不是一些边角料,人云亦云的东西,没吸引力 4) 校园经历纯没用 5)尽量少写减分项
听劝,我这个简历该怎么改...
点赞 评论 收藏
分享
压力很大,面试官全程高压,问的问题不难,但是没有任何反馈,很慌张,也无算法。实习问了20分钟,一直问我你们做的有什么用,总时长一小时1.学校都有什么课程2.spring的ioc原理以及优点3.除了解耦还知道什么?4.springboot与spring区别,二者的源码看过没?Tomcat了解嘛?有没有具体看过5.spring的bean,面试官一直在重复一个思想问我懂不懂,完全没听过6.mybatis是干什么的?ibatis用过没?平常怎么写SQL?完全不写嘛?7.设计一个分布式双十一秒杀系统(前端,网关,缓存,数据库防超卖全设计)8.怎么做限流9.缓存与数据库一致性,你做异步要用户等你嘛?10.负载均衡怎么做11.多数据中心还是单数据中心,如果出现没卖完怎么做(到这完全不会了,面试官直接说换个话题吧)12.平常读书吗?13.上过哲学课嘛?14.兴趣爱好有没有15.对ai的看法16.来深圳有问题嘛?17.为什么不考研18.上大学带给了你什么?你提升在哪里,有没有具体的例子?反问:1.现在手机都有应用市场,应用宝怎么盈利?除了手机应用市场还是有人用,现在在做跨端,微软都有合作,之后会进军mac,主要做游戏,腾讯本身就是游戏大户。2.面试表现?整体评价一下会给到反馈。面完直接变HR面,今天HR面后,已经转为录用评估了,来牛客许个愿,暑期现在还没什么面试,希望能拿个offer之后再考虑要不要留在手子吧。
nunuking:三面压力这么大吗,面试的会议约了多长时间呀
面试问题记录
点赞 评论 收藏
分享
评论
6
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务