请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。
解题思路
一个数值的表示方式为
A
[
.
[
B
]
]
[
e
∣
E
C
]
A[.[B]][e|EC]
A[.[B]][e∣EC],因此我们可以按照这个规则来判断。
关于本题需要考虑的几种情形
- 输入的字符串可能包含空格,首先需要去空
- 字符串为空肯定不是数值
- 小数点前后至少有一个部位包含数字,只有小数点那肯定不是数值,例如: 123. 123. 123. 以及 . 123 .123 .123都是数值,但只有一个(点)则不属于数值。
- 如果出现了字母 e e e或者 E E E,那么后面必须包含数字,并且一定是整数,小数不属于数值,例如: 12.34 e + 5.6 12.34e+5.6 12.34e+5.6不属于数值。
代码展示
class Solution {
public:
bool isNumber(string s) { //A[.[B]][e|EC]
while(!s.empty()&&s[0]==' ')s=s.substr(1);
while(!s.empty()&&s[s.length()-1]==' ')s = s.substr(0,s.length()-1);
// 去空操作
if (s.empty())return false;
int count = 0;
if (s[count]=='+' || s[count]=='-')count++;
bool flag = false;
while (count<s.length() && isdigit(s[count]))
{
count++;
flag = true; //整数部分有数字
}
if (s[count]=='.')
{
count++;
while (count<s.length() && isdigit(s[count]))
{
count++;
flag = true; //小数部分有数字
}
}
if(!flag)return false; //如果前面都不包含数字,肯定不是数值
if (s[count]=='e' || s[count]=='E')
{
flag = false; //E后面必须有数字
count++;
if (s[count]=='+' || s[count]=='-')count++;
while (count<s.length() && isdigit(s[count]))
{
count++;
flag = true;
}
}
return flag && (count==s.length()); //没有遍历完,肯定不是数值
}
};
另一种解法
对有限状态自动机感兴趣的可以学习一写这种解法
合法的结束状态有 2, 3, 7, 8 。代码按照图示先创建一个二维数组存放所有的对应关系,随后线性循环一一对应各种状态即可。
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)