LeetCode 第 65 题(Valid Number)
Validate if a given string is numeric.
Some examples:
“0” => true
” 0.1 ” => true
“abc” => false
“1 a” => false
“2e10” => trueNote: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
这道题是 LeetCode 的提交成功率最低的一道题,Acceptance 只有 12.1%。
其实倒不是这道题有多难,只是要考虑的情况比较多。都考虑清楚了,这道题也就做出来了。
首先呢,输入的字符串的前后可能会有多余的空格。因此第一步预处理就要把多余的空格去掉。下面的代码可以 完成这个功能。
string trim(string s)
{
string::const_iterator p1 = s.cbegin();
string::const_iterator p2 = s.cend();
while(p1 != s.cend())
{
if(*p1 != ' ')
{
break;
}
++ p1;
}
if(p1 == s.cend()) return string();
while(--p2 != p1)
{
if( *p2 != ' ')
{
break;
}
}
string ret(p1, ++p2);
return ret;
}
一个合理的数字要满足些什么条件?我简单的归纳了一下。应该有下面几点。
1.可能出现的字符包括”+-1234567890.eE”,出现其余的字符都说明不是合理的数字表示。
2.“+-”号只能出现在两个地方,字符串的最前面和 “eE” 之后紧贴着“eE”。
3.“.” 只能出现一次,而且“.”的前后必须有一边紧挨着数字。
4.“eE” 也只能出现一次,并且后面要跟着数字,“eE” 的前面只能是数字或“.”。
5.必须要出现数字,也就是 “12345678980” 至少要出来一个。
6.“+-”号后面要跟着数字或“.”。
下面是违反了这 6 条的一些例子:
- “ABC123” -> 不满足第 1 条。
- “12-2” -> 不满足第 2 条。
- “.” -> 不满足第 3 条。
- “..” -> 不满足第 3 条。
- “3.e” -> 不满足第 4 条。
- “3.e.” -> 不满足第 3 条 和 4 条。
- “” -> 不满足第 5 条。
- “-5e-” -> 不满足第 6 条。
- “.1e” -> 不满足第 4 条。
只要满足这 6 条,构成的字符串就是合理的数字表示。下面的代码就能完成对这六条规则的检测。代码不复杂,基本的原理是维护了一个状态机,当遍历完字符串后,如果状态机处在正确的状态上则说明这个字符串是合法的。
bool isNumber(string s)
{
s = trim(s); // 删除前后多余的空格
if(s.length() == 0) return false;
int state = 0; // 0 表示状态不确定 'e' 表示出现了 e , 2 表示是合法的数字
int dot = 0; // 暂时还没有出现小数点
int eE = 0; // 暂时还没有出现 e 或 E,所以 eE 的值为 0
string::const_iterator p = s.cbegin();
if(*p == '-' || *p == '+') ++p; // +- 号只能出现在两个位置,这是其中之一
if(*p == '.')
{
dot = 1;
state = '.';// 特殊状态,后面必须有数字
++p;
}
while(p != s.cend())
{
char c = tolower(*p);
if(state == 'e')
{
if(*p == '-' || *p == '+') // 这时 "+-" 号可以出现的另一合法位置
{
++p;
continue;
}
}
if(isdigit(c))
{
state = 2;
++ p;
continue;
}
if(c == 'e')
{
if(state != 2) return false;// 必须出现在数字或 . 之后
state = 'e';
eE ++;
if(eE > 1) return false;
++ p;
continue;
}
if( c == '.')
{
if(eE) return false;// . 不能出现在 e 的后面
state = 2;
dot ++;
if(dot > 1) return false;
++ p;
continue;
}
else
{
return false;
}
}
if(state == 2)
return true;
else
return false;
}