题目:力扣
解题思路:
做这道题运用的递归的思路。
我们从左到右进行匹配,若当前匹配成功地话,则最后的结果取决于后面是否也能匹配成功。若当前匹配失败的话,则直接返回失败。
我们从左到右对s的字符一个一个进行匹配。
首先,考虑特殊情形:
s.length() p.length() 结果 0 0 true 0 !0 不确定 !0 0 false !0 !0 不确定
可以看出,当p为空字符串的时候,结果取决于s是否是空字符串。这也是为什么一上来就判断p是不是空串。
- 当p为空串时,结果由s决定。
- 当p不为空串时,再执行下面的代码
我们接下来讨论当p不是空串的时候。
对s的字符挨个进行判断,对于s的第一个字符(要满足s不为空串),p的第一个字符是什么的时候才能正确匹配呢?我们能够确定s的第一个字符一定是字母,而p的第一个字符一定是字母或'.'
- 当p的第一个字符是字母时,且等于s的第一个字母时,一定能匹配。
- 当p的第一个字符是'.'时,因为'.'能够代表任意值,因此一定能匹配。
我们能够得到first的值了。
当first为true时,能够确定满足上面两条中的其中之一。
当前字符满足匹配了,我们需要考虑s下一个字符的匹配了。现在需要用到递归了。
- 满足条件2的情况比较简单,直接返回isMatch(s(1...len), p(1...len))
- 满足条件1时,也需要分情况讨论了:
- 第二个字符是*时,因为*可以代表多个前一个字符,所以需要保留第一个字符,以达到这种效果,返回isMatch(s(1...len), p)
- 第二个字符不是*时,直接返回isMatch(s(1...len), p(1...len))
当first为false的时候,能够确定的是s为空串,或者是p的第一个字符其实就是字母和s的不相等。
- 当p的第二个字符是*的时候,虽然第一个字母和s不匹配,但是因为a*可以代表零个字母,可以忽略*和*号前面的字母,返回isMatch(s, p(2...len))
- 当p的第二个字符不是*的时候,无论怎样,第一个字符都不能去掉也无法匹配,因此可以直接返回false。
class Solution {
public boolean isMatch(String s, String p) {
if(p.isEmpty()){
return s.isEmpty();
}
boolean first = !s.isEmpty() && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.');
if(first){
if(p.length()>=2 && p.charAt(1) == '*')
return isMatch(s.substring(1),p);
else
return isMatch(s.substring(1), p.substring(1));
}
else{
return p.length()>=2 && isMatch(s, p.substring(2));
}
}
}