分析错误在什么地方也是非常好的熟悉算法的过程,尤其是一些很难发现的小细节。。
分类:举个例子,比如把人进行分类
你非得分成0岁的,1岁的。。。。100岁的,有时候程序给个108岁的你就认为不对;
分成男人和女人不就好了,分类的标准要简单--不要太多分支,其次要保证考虑到所有的情形,保证健壮性。
错误解答:
bool isMatch(string s, string p) {
if (p.empty())
return s.empty();
if (s[0] != p[0] || p[0] != '.') //!!!!!!这里没有考虑到s为空的时候的情况
return false;
if (p.length()>=2 && p[1] == '*')//确保不越界
return isMatch(s, p.substr(2)) || (!s.empty()&&isMatch(s.substr(1), p));
if (s[0] == p[0] || p[0] == '.')
return !s.empty() && isMatch(s.substr(1), p.substr(1));
return false;
}
注意上面注释 //!!!!!!这里没有考虑到s为空的时候的情况
这里就没有考虑到s为空的时候,那么s[0]=空字符(注意这里没有越界),这个时候考虑 p="z*";我们把代码走一遍,会直接返回false;
考虑 s="aa",p="a*";满足第3个条件, 接下来是子问题1::判断 s="aa",p="";很容易知道返回false;
子问题2:s="a",p="a*"; 满足第3个条件,又是子问题 1:判断 s="a",p="",返回false;
子问题2:s="",p="a*",满足第二个条件,返回false;
其实将一个问题进行分类判断是最关键的,在剪枝的过程中怎么确保条件是充要条件。
下面是青铜段位的答案,特点---考虑全面,容易思考,缺点:没有简化不必要的操作,或者有重复操作,即分类冗余了;
bool isMatch(string s, string p) {
cout << s << " " << p << endl;
if (p.empty())
return s.empty();
if (p.length() == 1) {
if (s.empty())
return false;
else{
if (s[0] == p[0] || p[0] == '.')
return isMatch(s.substr(1), p.substr(1));
else
return false;
}
}
else { //p.length()>=2
if (p[1] == '*') {
if (s.empty())
return isMatch(s, p.substr(2));
if (s[0] == p[0] || p[0] == '.')
return isMatch(s, p.substr(2)) || isMatch(s.substr(1), p);
else
return isMatch(s, p.substr(2));
}
else {
if (s.empty())
return false;
else {
if (s[0] == p[0] || p[0] == '.')
return isMatch(s.substr(1), p.substr(1));
else
return false;
}
}
}
//return true;
}
钻石段位的答案:这里分享链接自己看去,点个赞--------- https://leetcode-cn.com/problems/regular-expression-matching/comments/86480
一些简化的方法:
if(A)
return B;
else
return C;
等价于:
return A&&B;
这个问题真的很好,反映了很多问题,至少对我而言。
------更新
分析完leetcode44之后我用DP又做了一遍;
bool isMatch(string s, string p) {
int M = s.length();
int N = p.length();
vector<vector<bool>> v(M+1, vector<bool>(N+1, false));
v[0][0] = true;
for (int j=1; j <= N; j++) {
if (p[j-1] == '*')
v[0][j] = v[0][j - 2];
}
for (int i = 1; i <= M; i++) {
for (int j = 1; j <= N; j++) {
if (p[j - 1] == '*') {
if (p[j - 2] == s[i - 1]||p[j-2]=='.')
v[i][j] = v[i][j - 2] || v[i - 1][j];
else
v[i][j] = v[i][j - 2];
}
if (p[j-1] == '.' || p[j-1] == s[i-1])
v[i][j] = v[i - 1][j - 1];
}
}
for (int i = 0; i <= s.length(); i++) {
for (int j = 0; j <= p.length(); j++) {
cout << s.substr(0, i) << "--" << p.substr(0, j) << "--" << v[i][j] << endl;
}
}
return v[M][N];
}