题目描述
给定一个字符串 (s) 和一个字符模式 § ,实现一个支持 ‘?’ 和 ‘*’ 的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 ? 和 *。
示例 1:
输入:
s = "aa"
p = "a"
输出: false
解释: "a" 无法匹配 "aa" 整个字符串
示例 2:
输入:
s = "aa"
p = "*"
输出: true
解释: '*' 可以匹配任意字符串。
示例 3:
输入:
s = "cb"
p = "?a"
输出: false
解释: '?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。
示例 4:
输入:
s = "adceb"
p = "*a*b"
输出: true
解释: 第一个 '*' 可以匹配空字符串, 第二个 '*' 可以匹配字符串 "dce".
示例 5:
输入:
s = "acdcb"
p = "a*c?b"
输出: false
解法
cpp
class Solution {
public:
bool isMatch(string s, string p) {
int i = 0, j = 0, iStar = -1, jStar = -1, aLen = s.size(), pLen = p.size();
while (i < aLen) {
if (j < pLen && (s[i] == p[j] || p[j] == '?')) {
++i, ++j;
} else if (j < pLen && p[j] == '*') {
iStar = i;
jStar = j++;
} else if (iStar >= 0) {
i = ++iStar;
j = jStar + 1;
} else return false;
}
while (j < pLen && p[j] == '*') ++j;//去除多余星号
return j == pLen;
}
};
解题思路
双指针
由题目可以得出结论
1.当s[i]==p[j]时,这里i和j分别表示字符s和字符p的下标,结果为true,然后遍历下一个字符
2.当p[j] =’?’,由于’?'可以表示一个字符,结果也为true,继续遍历下一个字符,这里可以和第一点结合表示
(s[i] == p[j] || p[j] == '?')
3.当p[j] =’’,由于 ‘’’ 可以匹配任意字符串,继续往下遍历s[i] ,直到下一个p[j]!=’*’
所以,就可以使用双指针进行遍历
用iStar和jStar表示星号在s和p中匹配的位置,初始值为-1,i和j表示当前匹配的位置,匹配过程如下:
- 如果s和p中字符匹配,则分别自增i和j
- 如果p中当前字符为’*’,则标记
iStar
和jStar
,同时自增j,进行下一轮的s[i]和p[j]的匹配 - 如果iStar >= 0,并且上述的1、2点条件都不满足,表示之前匹配过’’,因为’'可以匹配任意字符串,所以继续递增i,同时移动j为jStar下一个字符,直到下一个s[i]和p[j]满足1,2点条件
4.不符合上面的条件返回false
当匹配 s=“ab”,p=ab时,虽然s字符串已经遍历完,还需要继续遍历p中’'字符
bool isMatch(string s, string p) {
int i = 0, j = 0, iStar = -1, jStar = -1, aLen = s.size(), pLen = p.size();
while (i < aLen) {
if (j < pLen && (s[i] == p[j] || p[j] == '?')) {
++i, ++j;
} else if (j < pLen && p[j] == '*') {
iStar = i;
//下个循环s[i]和p[j]的匹配
jStar = j++;
} else if (iStar >= 0) {
i = ++iStar;
j = jStar + 1;
} else return false;
}
while (j < pLen && p[j] == '*') ++j;//去除多余星号
return j == pLen;
}