Skip to content

Commit 1cb9265

Browse files
committed
daily update
1 parent 60d943b commit 1cb9265

File tree

9 files changed

+856
-19
lines changed

9 files changed

+856
-19
lines changed

pom.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
<version>1.0-SNAPSHOT</version>
1010

1111
<name>leetcode</name>
12-
<!-- FIXME change it to the project's website -->
13-
<url>http://www.example.com</url>
12+
<url>http://www.github.com/dingjianhub/leetcode</url>
1413

1514
<properties>
1615
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
2+
3+
# 10_RegularExpressionMatching_正则表达式匹配
4+
5+
## 📌题目详情
6+
7+
[leetcode 题目地址](https://leetcode.com/problems/regular-expression-matching/)
8+
9+
[leetcode-cn 题目地址](https://leetcode-cn.com/problems/regular-expression-matching/)
10+
11+
📗Difficulty: **Hard**
12+
13+
🎯Tags:
14+
15+
+ **[Dynamic Programming](https://leetcode.com/tag/dynamic-programming/)**
16+
+ **[String](https://leetcode.com/tag/string/)**
17+
18+
---
19+
20+
## 📃题目描述
21+
22+
给你一个字符串 `s` 和一个字符规律 `p`,请你来实现一个支持 `'.'``'*'` 的正则表达式匹配。
23+
24+
```
25+
'.' 匹配任意单个字符
26+
'*' 匹配零个或多个前面的那一个元素
27+
```
28+
29+
所谓匹配,是要涵盖 **整个** 字符串 `s`的,而不是部分字符串。
30+
31+
**说明:**
32+
33+
+ `s` 可能为空,且只包含从 `a-z` 的小写字母。
34+
+ `p` 可能为空,且只包含从 `a-z` 的小写字母,以及字符 `.``*`
35+
36+
37+
38+
**样例 1:**
39+
40+
```
41+
输入:
42+
s = "aa"
43+
p = "a"
44+
输出: false
45+
解释: "a" 无法匹配 "aa" 整个字符串。
46+
```
47+
48+
49+
50+
**样例 2:**
51+
52+
```
53+
输入:
54+
s = "aa"
55+
p = "a*"
56+
输出: true
57+
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
58+
```
59+
60+
61+
62+
**样例 2:**
63+
64+
```
65+
输入:
66+
s = "aa"
67+
p = "a*"
68+
输出: true
69+
解释: 因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。
70+
```
71+
72+
73+
74+
**样例 3:**
75+
76+
```
77+
输入:
78+
s = "ab"
79+
p = ".*"
80+
输出: true
81+
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。
82+
```
83+
84+
85+
86+
**样例 4:**
87+
88+
```
89+
输入:
90+
s = "aab"
91+
p = "c*a*b"
92+
输出: true
93+
解释: 因为 '*' 表示零个或多个,这里 'c' 为 0 个, 'a' 被重复一次。因此可以匹配字符串 "aab"。
94+
```
95+
96+
97+
98+
**样例 5:**
99+
100+
```
101+
输入:
102+
s = "mississippi"
103+
p = "mis*is*p*."
104+
输出: false
105+
```
106+
107+
108+
109+
## 🏹🎯解题思路
110+
111+
112+
113+
#### 代码实现
114+
115+
```java
116+
// 来自 《leetcode && 拉钩网 300 分钟搞定算法面试》
117+
// 不是特别好的递归算法,其中细节考虑很多
118+
public class Solution1 {
119+
// 从前往后进行分析,进行递归操作
120+
public boolean isMatch(String s, String p) {
121+
if (s == null || p == null) {
122+
return false;
123+
}
124+
return isMatch(s, 0, p, 0);
125+
}
126+
127+
public boolean isMatch(String s, int i, String p, int j) {
128+
int m = s.length();
129+
int n = p.length();
130+
131+
// 递归结束的时间:j 遍历完 p 字符串,即可跳出递归
132+
// 如果 i 也刚好完成遍历,那么 s 和 p 完全匹配
133+
if (j == n) {
134+
return i == m;
135+
}
136+
137+
// j 的后一个字符不是 '*' , 直接递归调用 isMatch 方法即可
138+
if (j == n - 1 || p.charAt(j + 1) != '*') {
139+
// i < m , 在 p 比 s 长的情况,此时也不匹配
140+
return (i < m) && firstMatch(s, i, p, j) && isMatch(s, i + 1, p, j + 1);
141+
}
142+
143+
// j 的后一个字符是 '*'
144+
// 一种特殊的情况是,'*' 是最后一个字符
145+
if (j < n - 1 && p.charAt(j + 1) == '*') {
146+
// while 循环是本题核心
147+
while ((i < m) && firstMatch(s, i, p, j)) {
148+
if (isMatch(s, i, p, j + 2)) {
149+
return true;
150+
}
151+
// 如果无法匹配
152+
// 尝试用星号组合去匹配更长的一段字符串
153+
i++;
154+
}
155+
}
156+
157+
// 当 i 和 j 指向字符不相同
158+
// 或 i 已经遍历完 s 字符串,同时 j 指向的字符后面跟着一个 '*' 的情况
159+
// 使用 '*' 号组合表示为一个空字符串,然后递归下去
160+
if (((i < m) && !firstMatch(s, i, p, j)) || (i == m && p.charAt(j + 1) == '*')) {
161+
return isMatch(s, i, p, j + 2);
162+
}
163+
164+
// 初始调用输入为 i,j 为超过 实际长度的 情况,返回 false
165+
return false;
166+
}
167+
168+
public boolean firstMatch(String s, int i, String p, int j) {
169+
// 判断 i,j 指针所指字符是否相等
170+
// 如果 j 位置字符为 '.' , 那么也认为是相等的
171+
return p.charAt(j) == '.' || s.charAt(i) == p.charAt(j);
172+
}
173+
174+
public static void main(String[] args) {
175+
String s1 = "aa";
176+
String p1 = "a";
177+
System.out.println(new Solution1().isMatch(s1, p1));
178+
179+
String s2 = "aa";
180+
String p2 = "a*";
181+
System.out.println(new Solution1().isMatch(s2, p2));
182+
183+
String s3 = "ab";
184+
String p3 = ".*";
185+
System.out.println(new Solution1().isMatch(s3, p3));
186+
187+
String s4 = "aab";
188+
String p4 = "c*a*b";
189+
System.out.println(new Solution1().isMatch(s4, p4));
190+
191+
String s5 = "mississippi";
192+
String p5 = "mis*is*p*.";
193+
System.out.println(new Solution1().isMatch(s5, p5));
194+
195+
String s6 = "ssippi";
196+
String p6 = "s*p*.";
197+
System.out.println(new Solution1().isMatch(s6, p6));
198+
199+
}
200+
}
201+
```
202+
203+
204+
205+
#### 复杂度分析
206+
207+
+ 时间复杂度:
208+
+ 空间复杂度:
209+
210+
211+
212+
## 💡总结
213+
214+
215+

src/main/java/ltd/ryantech/string/regularExpressionMatching10/Solution1.java

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* @create 2020/05/29 15:46
1313
**/
1414

15+
// 来自 《leetcode && 拉钩网 300 分钟搞定算法面试》
16+
// 不是特别好的递归算法,其中细节考虑很多
1517
public class Solution1 {
1618
// 从前往后进行分析,进行递归操作
1719
public boolean isMatch(String s, String p) {
@@ -31,41 +33,67 @@ public boolean isMatch(String s, int i, String p, int j) {
3133
return i == m;
3234
}
3335

34-
// 字符 match 的情况:j 指向的字符为 '.' 或者是 i,j 指针各自指向的字符完全相等
35-
boolean charMatch = (p.charAt(j) == '.') || s.charAt(i) == p.charAt(j);
36-
3736
// j 的后一个字符不是 '*' , 直接递归调用 isMatch 方法即可
3837
if (j == n - 1 || p.charAt(j + 1) != '*') {
3938
// i < m , 在 p 比 s 长的情况,此时也不匹配
40-
return (i < m) && charMatch && isMatch(s, i + 1, p, j + 1);
39+
return (i < m) && firstMatch(s, i, p, j) && isMatch(s, i + 1, p, j + 1);
4140
}
4241

43-
// j 在有效范围内,且 j 不是 s 的最后一个字符
42+
// j 的后一个字符是 '*'
43+
// 一种特殊的情况是,'*' 是最后一个字符
4444
if (j < n - 1 && p.charAt(j + 1) == '*') {
4545
// while 循环是本题核心
46-
while ((i < m) && charMatch) {
46+
while ((i < m) && firstMatch(s, i, p, j)) {
4747
if (isMatch(s, i, p, j + 2)) {
4848
return true;
49-
5049
}
5150
// 如果无法匹配
5251
// 尝试用星号组合去匹配更长的一段字符串
5352
i++;
5453
}
5554
}
5655

57-
if (!charMatch || (i == m && p.charAt(j + 1) == '*')) {
56+
// 当 i 和 j 指向字符不相同
57+
// 或 i 已经遍历完 s 字符串,同时 j 指向的字符后面跟着一个 '*' 的情况
58+
// 使用 '*' 号组合表示为一个空字符串,然后递归下去
59+
if (((i < m) && !firstMatch(s, i, p, j)) || (i == m && p.charAt(j + 1) == '*')) {
5860
return isMatch(s, i, p, j + 2);
5961
}
62+
63+
// 初始调用输入为 i,j 为超过 实际长度的 情况,返回 false
6064
return false;
6165
}
6266

67+
public boolean firstMatch(String s, int i, String p, int j) {
68+
// 判断 i,j 指针所指字符是否相等
69+
// 如果 j 位置字符为 '.' , 那么也认为是相等的
70+
return p.charAt(j) == '.' || s.charAt(i) == p.charAt(j);
71+
}
72+
6373
public static void main(String[] args) {
64-
String s1 = "ssippi";
65-
String p1 = "s*p*.";
74+
String s1 = "aa";
75+
String p1 = "a";
6676
System.out.println(new Solution1().isMatch(s1, p1));
67-
// String s1 = "aa";
68-
// String p1 = "a*";
69-
// System.out.println(new Solution1().isMatch(s1, p1));
77+
78+
String s2 = "aa";
79+
String p2 = "a*";
80+
System.out.println(new Solution1().isMatch(s2, p2));
81+
82+
String s3 = "ab";
83+
String p3 = ".*";
84+
System.out.println(new Solution1().isMatch(s3, p3));
85+
86+
String s4 = "aab";
87+
String p4 = "c*a*b";
88+
System.out.println(new Solution1().isMatch(s4, p4));
89+
90+
String s5 = "mississippi";
91+
String p5 = "mis*is*p*.";
92+
System.out.println(new Solution1().isMatch(s5, p5));
93+
94+
String s6 = "ssippi";
95+
String p6 = "s*p*.";
96+
System.out.println(new Solution1().isMatch(s6, p6));
97+
7098
}
7199
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package ltd.ryantech.string.regularExpressionMatching10;
2+
3+
/**
4+
* @author jerry
5+
* @program leetcode
6+
* @package_name ltd.ryantech.string.regularExpressionMatching10
7+
* @description 正则表达式匹配
8+
* @leetcode_CN_url // https://leetcode-cn.com/problems/regular-expression-matching/
9+
* @leetcode_US_url // https://leetcode.com/problems/regular-expression-matching/
10+
* @hard_level Hard
11+
* @tag String // https://leetcode-cn.com/tag/string/
12+
* @create 2020/05/30 15:28
13+
**/
14+
15+
public class Solution2 {
16+
public boolean isMatch(String s, String p) {
17+
return false;
18+
}
19+
20+
public static void main(String[] args) {
21+
22+
}
23+
}

0 commit comments

Comments
 (0)