请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(’+’ 或 ‘-’)
下述格式之一:
至少一位数字,后面跟着一个点 ‘.’
至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符(’+’ 或 ‘-’)
至少一位数字
部分数值列举如下:
["+100", “5e2”, “-123”, “3.1416”, “-1E-16”, “0123”]
部分非数值列举如下:
[“12e”, “1a3.14”, “1.2.3”, “±5”, “12e+5.4”]
示例 1:
输入:s = “0”
输出:true
示例 2:
输入:s = “e”
输出:false
示例 3:
输入:s = “.”
输出:false
示例 4:
输入:s = " .1 "
输出:true
提示:
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 ‘+’ ,减号 ‘-’ ,空格 ’ ’ 或者点 ‘.’ 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
——难度:中等
思路如下:
代码如下:
class Solution {
public:
//有限状态自动机DFA,时间复杂度O(N)
typedef pair<char, int> charint;
bool isNumber(string s) {
vector<map<char, int> > states = { //states[s][t] = x 表示当前状态为s,遇到了编码为t的字符后,状态转为x
map<char, int>{charint(' ', 0), charint('s', 1), charint('d', 2), charint('.', 4)}, //状态0转移
map<char, int>{charint('d', 2), charint('.', 4)}, //状态1转移
map<char, int>{charint('d', 2), charint('.', 3), charint('e', 5), charint(' ', 8)}, //状态2转移
map<char, int>{charint('d', 3), charint('e', 5), charint(' ', 8)}, //状态3转移
map<char, int>{charint('d', 3)}, //状态4转移
map<char, int>{charint('s', 6), charint('d', 7)}, //状态5转移
map<char, int>{charint('d', 7)}, //状态6转移
map<char, int>{charint('d', 7), charint(' ', 8)}, //状态7转移
map<char, int>{charint(' ', 8)} //状态转移
};
int p = 0; //开始状态为0
char t;
for(int i = 0; i < s.size(); i++) { //遍历该字符串
if (s[i] >= '0' && s[i] <= '9') //该字符为数字
t = 'd';
else if (s[i] == '+' || s[i] == '-') //该字符为符号('+'或'-')
t = 's';
else if (s[i] == '.' || s[i] == ' ') //该字符问为 小数点 或 空格
t = s[i];
else if (s[i] == 'e' || s[i] == 'E') //该字符为'e'或'E'
t = 'e';
else //剩下的就是未知符号了
t = '?';
if (states[p].count(t)) //在当前状态p下,看下有没有遇到编码为t的字符后 可以转移的状态
p = states[p][t]; //如果执行了这条语句,说明有可以转移的状态
else
return false; //如果执行了这条语句,说明没有可以转移的状态
}
return p == 2 || p == 3 || p == 7 || p == 8; //如果最终状态为2、3、7、8中的其中一个,说明该字符串表示数值
}
};