题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、“±5”、"-1E-16"及"12e+5.4"都不是。
解题思路
下面是DFA:
注:
- 用一个vector内层使用map来保存状态之间的转移。
- 去掉首位空格后建立的自动机,加上空格也可以,只是状态会多出来一个(尾部多出一个识别空格的状态)。
- 小数点前面可以没有数字,对应状态8。
- 小数点后面也可以没有数字,对应状态3为接收状态和3后面直接跟e指数等。
- 接受状态:2、3、4、7。
代码
class Solution {
public:
bool isNumber(string s) {
if(s.size() == 0){
return false;
}
//运用状态机进行判断
//1.先去掉首尾空格
int n = s.size();
int start = 0;
int end = n - 1;
//全部是空格的字符串
while(start < n && s[start] == ' '){
++start;
}
if(start == n){
return false;
}
while(end >= 0 && s[end] == ' '){
--end;
}
//然后用状态机进行判断,一共8个状态:
int state = 0;
//状态机判断
judge(s, start, end, state);
if(state == 2 || state == 3 || state == 4 || state == 7){
return true;
}
return false;
}
private:
//状态机的9个状态,2、3、4、7是接收状态
//0.初始状态
//1.含有底数前符号+/-
//2.小数点前数字
//3.小数点
//4.小数点后数字
//5.e指数
//6.e后面指数的符号
//7.指数的数字
//8.小数点前没有数字
vector<unordered_map<char, int>> myMap;
void judge(string s, int start, int end, int &state){
myMap = vector<unordered_map<char, int>>(9);
myMap[0] = {{'+', 1}, {'-', 1}, {'d', 2}, {'.', 8}}; //注:小数点前没有数字也符合
myMap[1] = {{'d', 2}, {'.', 8}};
myMap[2] = {{'d', 2}, {'.', 3}, {'e', 5}};
myMap[3] = {{'d', 4}, {'e', 5}};
myMap[4] = {{'d', 4}, {'e', 5}};
myMap[5] = {{'+', 6}, {'-', 6}, {'d', 7}};
myMap[6] = {{'d', 7}};
myMap[7] = {{'d', 7}};
myMap[8] = {{'d', 4}};
for(int i = start; i <= end; ++i){
char c = s[i];
if(c >= '0' && c <= '9'){ //数字
c = 'd';
if(myMap[state].count(c)){
state = myMap[state][c];
}
else{ //非法输入,不能进行状态转换,直接将state置为0
state = 0; //0不是接收状态,置为0,然后返回
return;
}
}
else{
if(myMap[state].count(c)){
state = myMap[state][c];
}
else{ //非法输入,不能进行状态转换,直接将state置为0
state = 0; //0不是接收状态,置为0,然后返回
return;
}
}
}
}
};