周末也没有做leetcode,感觉有点罪恶啊,这个第10题好难啊,涉及到递归了,看的我是头晕眼花啊。我看着看着还是有点收获的,我发现题目仍然没有我想象中的那么的简单,如果s = 'a b c d e',p = '. * e',这样匹配出的结果也是正确的,我就很纳闷儿啊,' . '是匹配任意一个字符,可是我以为只能匹配一个字符,但是从这个算例上看,当它和' * '在一起时,' . '可以多次匹配不同的字符,这个是我不太明白的地方。。好的吧,这样也让我更加的明白了题意。这个题真的是很难啊!!
有篇博文写的这个题目的分析挺不错的,可以让人看得懂,链接是:leetcode 10 题目分析。因为这个分析使用Java写的代码,我把它改成了C++版本并在leetcode上通过了测试。回到题目分析中,里面的表格就是分析的思路和过程,这个表格非常的重要,为了逻辑清楚,先对p做条件判断,在此基础上,再对s做条件判断。
说明:
对于第4个条件:当p的第二个字符不是星号时,如果S不空且(p.charAt(0) == s.charAt(0) 或者 p.charAt(0)==‘ . ’),则进入下一层递归继续比较分别截取首元素的s和p;否则,返回false。
对于第5个条件:当p的第二个字符是星号时,如果S不空且(p.charAt(0) == s.charAt(0) 或者 p.charAt(0)==‘ . ’),有两种分支需要分别判断:
1、某字符+星号不要匹配s的首字符:(因为星号之前的字符可出现可不出现,该情况不配是考虑到后面有必须匹配的。假设当前匹配并截去s的首字符,会导致后续匹配错误。) 截去p的前两个元素(某字符+星号)并进入下一层递归,假如返回true,则当前递归返回true;假如返回false,进入分支2。
2、某字符+星号要匹配s的首字符:截去s首字符并继续条件5的判断。
对于第6个条件:当p的第二个字符是星号时,非【S不空且(p.charAt(0) == s.charAt(0) 或者 p.charAt(0)==‘ . ’)】,截去p的前两个元素(某字符+星号)并进入下一层递归。
下面是我修改的C++版本的代码:
class Solution {
public:
bool isMatch(string s, string p) {
if (p.size() == 0) { //对应步骤1
if(s.size() == 0)
return true;
else
return false;
}
if (p.length() == 1 || p[1] != '*') { //对应步骤2,3,4
if (s.size() == 0 || (p[0] != '.' && p[0] != s[0]))
return false;
else
return isMatch(s.substr(1), p.substr(1));
}
while (s.size() != 0 && (s[0] == p[0] || p[0] == '.')) { //对应步骤5,6
if (isMatch(s, p.substr(2)))
return true;
s = s.substr(1);
}
return isMatch(s, p.substr(2));
}
};
现在这个题我还没有缓过劲儿来,我得再想想。。。