【LeetCode热题100】打开第6天:正则表达式匹配

news/2024/7/2 23:39:08

文章目录

  • 正则表达式匹配
    • ⛅前言
    • 🔒题目
    • 🔑题解

正则表达式匹配

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

🔒题目

原题链接:10. 正则表达式匹配 - 力扣(LeetCode)

在这里插入图片描述

🔑题解

  • 解法一:正则表达式

    这里标记是困难,但是如果使用正则表达式一行代码就解决了,但是这题的作者可能并不是想要我们使用正则表达式,而是使用动态规划,如果使用动态规划这题难度直接上升几个等级。所以大家不要为了做题而做题,而是去学习了解更多的算法思路,有时候我们不需要去把一个题给AC了,而是要做到,看到一个题能够第一时间直到这题考察的内容,应该使用哪种算法策略,毕竟现在AI这么流行,直接把一个题交给AI,他立马能够给你解答。

    当然这题使用正则也不赖,也是一种比较优秀的解法,但是却无法锻炼到我们的逻辑思维,因为太简单了🤣正则表达式YYDS

    import java.util.regex.Pattern;
    
    class Solution {
        public boolean isMatch(String s, String p) {
            return Pattern.matches(p, s);
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n ) O(n) O(n),正则匹配本质是
    • 空间复杂度: O ( 1 ) O(1) O(1)

    其中 n n n 为字符串的长度

  • 解法二:动态规划

    本段代码来自这位大佬的:fomalhaut1998 - 力扣(LeetCode)

    class Solution {
        public boolean isMatch(String s, String p) {
            /*
            dp五部曲:
            设主串s的长度为m,设模式串p的长度为n;其中s只有小写字母,p有字母/./*
            1.状态定义:dp[i][j]为考虑s[0,i-1]与p[0,j-1]是否能匹配上,能匹配上就为true
            2.状态转移:若要求dp[i][j]就必须考虑到s[i-1]与p[j-1]
                2.1 当p[j-1]不是'*'时
                    2.1.1 若s[i-1]==p[j-1]时,即p[j-1]为'a'-'z'且与s[i-1]相等,看dp[i-1][j-1]
                    2.1.2 p[j-1] == '.'时,直接将'.'变成s[i-1],看dp[i-1][j-1]
                    注意:这里的'.'是匹配一个字符,而不是一连串,如"a.b"->"axb"
                2.2 当p[j-1]是'*'时,主要看p[j-2]做判断
                    2.2.1 p[j-2]为'a'-'z'并且p[j-2]==s[i-1],那么此时s继续往前看,p暂时不动
                        即:看dp[i-1][j]
                    2.2.2 p[j-2]为'.',那么".*"可以变为"....."可以匹配s[i-1]前面的任何字符(万能串)
                        因此,直接看dp[i-1][j](或者直接返回true)
                    2.2.3 剩下的就是p[j-2]为'a'-'z'且p[j-2]!=s[i-1],那么此时p的"x*"作废,看dp[i][j-2]
                这里:2.1.1与2.2.2可以看成一种情形:即s与p均前移一位
                    2.2.1与2.2.2可以看成一种情形:即p不动s前移一位
            3.初始化:
                3.1 空的s
                    3.1.1 空的p,空的s可以匹配空的p,因此dp[0][0]=true
                    3.1.2 非空的p,空的s可能可以匹配非空的p,例如"a*",因此需要经过转移计算
                3.2 空的p
                    3.2.1 空的s,同3.1.1
                    3.2.2 非空的s,空的p不可能匹配非空的s,因此dp[i][0]=false,i∈[1,m]
                3.3 非空的s与非空的p:需要经过转移计算
                其中:3.1.1与3.2.2可以合并为dp[i][0]=i==0
            4.遍历顺序:显然是正序遍历
            5.返回形式:返回dp[m][n]就是考虑s[0,m-1]与p[0,n-1]是否能匹配上
            */
            int m = s.length(), n = p.length();
            boolean[][] dp = new boolean[m + 1][n + 1];
            // 初始化dp[i][0]
            // for(int i = 0; i <= m; i++) {
            //     dp[i][0] = i == 0;
            // }
            dp[0][0] = true;
            // i从0开始
            for(int i = 0; i <= m; i++) {
                // 注意j从1开始
                for(int j = 1; j <= n; j++) {
                    if(p.charAt(j - 1) != '*') {
                        // 1.当p[j-1]不是'*'时(注意j已经从1开始了)
                        // 这里要注意运算优先级问题(加括号)
                        if(i >= 1 && (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '.')) {
                            // s与p均前移一位
                            dp[i][j] = dp[i - 1][j - 1];
                        }
                    } else {
                        // 2.当p[j-1]是'*'时,主要看p[j-2]做判断
                        if(j >= 2 && i >= 1 && 
                        (p.charAt(j - 2) == s.charAt(i - 1) || p.charAt(j - 2) == '.')) {
                            // 看"x*":p不动s前移一位
                            dp[i][j] = dp[i - 1][j];
                        }
                        // 不看"x*":
                        // 剩下的为p[j-2]为'a'-'z'且p[j-2]!=s[i-1],那么此时p的"x*"作废,看dp[i][j-2]
                        if(j >= 2) {
                            dp[i][j] |= dp[i][j - 2];
                        }
                        // 这里的|=表示只要满足了其中一个条件就可以使得dp[i][j]==true
                        // 通俗一点的解释就是:当p[j-1]=='*'时,
                        // 若p[j-2]==s[i-1]||p[j-2]=='.',则dp[i][j]可以继承dp[i-1][j]:转移路径1
                        // 若p[j-2]!=s[i-1],则dp[i][j]可以继承dp[i][j-2]:转移路径2
                        // 满足任意一条转移路径就可以使得dp[i][j]=true
                    }        
                }
            }
            // 所求即为考虑s[0,m-1]与p[0,n-1]是否能匹配上
            return dp[m][n];
        }
    }
    

    详情参考官方代码

    复杂度分析:

    • 时间复杂度: O ( n ∗ m ) O(n*m) O(nm)
    • 空间复杂度: O ( n ∗ m ) O(n*m) O(nm)

    其中 n n n 为数组中元素的个数


http://lihuaxi.xjx100.cn/news/1178909.html

相关文章

【刷题之路】LeetCode 2073. 买票需要的时间

【刷题之路】LeetCode 2073. 买票需要的时间 一、题目描述二、解题1、方法1——记录每个人需要的时间1.1、思路分析1.2、代码实现 2、方法2——队列记录下标2.1、思路分析2.2、先将队列实现一下2.3、代码实现 一、题目描述 原题连接&#xff1a; 2073. 买票需要的时间 题目描述…

序列化_原理与应用

关键字&#xff1a;序列化,java,proto,json,字节序列,字节数组,byte array,serialize序列化简介 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。 如在内存中的java对象&#xff08;本是方便JVM使用的格式&#xff09;序列化为硬盘或是网络传输…

关于linux系统can收发,以及jetson系列can收发的说明,以及SN65HVD230 CAN board和MCP2515和TJA1050的区别是什么?

1&#xff0c;jetson orin、Tx2有can处理器&#xff0c;没有收发器 所以官方推荐用SN65HVD230 CAN board就可以了。理论上单独的TJA1050也是可以的。。。 2&#xff0c;如果本身没有can像jetson nano、香橙派这样&#xff0c;就需要使用MCP2515和TJA1050的结合体了 SN65HVD230…

HCIA-MSTP替代技术之链路捆绑(手工模式)

目录 1&#xff0c;网络的可靠性需求 2&#xff0c;链路聚合原理 链路聚合&#xff1a; 聚合组(Link Aggregation Group&#xff0c;LAG)&#xff1a; 成员接口和成员链路&#xff1a; 活动接口和活动链路&#xff1a; 非活动接口和非活动链路&#xff1a; 聚合模式&…

termux的一些问题

我的电脑过安检的时候&#xff0c;竟然被卡住&#xff0c;压坏了。没办法&#xff0c;有需要电脑工作。我就用家里的平板电脑工作。我首先安装了termux&#xff0c;但是遇到这些问题。 (1)我在平板电脑上安装了termux后&#xff0c;我想通过手机登陆到平板电脑&#xff0c;但是…

基于Open3D的点云处理4-数据结构Kdtree和Octree

Kdtree Kdtree是一种划分k维数据空间的数据结构&#xff0c;本质也是一颗二叉树&#xff0c;只不过每个节点的数据都是k维&#xff0c;当k1时&#xff0c;就是普通二叉树。 建立Kdtree实际上是一个不断划分的过程&#xff0c;首先选择最sparse的维度&#xff08;一般通过计算…

内网渗透(八十五)之ADCS证书服务攻击

ADCS证书服务攻击 漏洞背景 2021年6月17日,国外安全研究员 Will Schroeder 和 Lee Christensen 共同发布了针对ADCS(Active Directory Certificate Service, 活动目录证书服务)的攻击手法。同年8月5日,在Black Hat 2021上 Will Schroeder 和 Lee CHristensen 对该攻击手法进…

【JVM】11. 垃圾回收及回收算法算法

文章目录 11.1. 垃圾回收概述11.1.1. 什么是垃圾&#xff1f;什么是垃圾&#xff1f; 11.1.2. 为什么需要GC11.1.3. 早期垃圾回收11.1.4. Java垃圾回收机制担忧GC主要关注的区域 11.2. 垃圾回收相关算法11.2.1. 标记阶段&#xff1a;引用计数算法方式一&#xff1a;引用计数算法…