用DFA验证字符串中的数字
背景描述
有效数字(按顺序)可以分成以下几个部分:
- 一个 小数 或者 整数
- (可选)一个 ’e’ 或 ‘E’ ,后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-’)
- 下述格式之一:
- 至少一位数字,后面跟着一个点 ‘.’
- 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
- 一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-’)
- 至少一位数字
部分有效数字列举如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
提示
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 ‘+’ ,减号 ‘-’ ,或者点 ‘.’ 。
模拟
这种方式就是按照字符串的规律,写对对应的代码,来判断输入的字符串是否正确
模拟过程如下:
- 去掉开头、结尾的空格符(这步可以省略,按照提示字符串不包含空格)
- 如果是空串直接返回错误
- 判断开头的 + -,如果(+-)后面是空,则返回错误
- 处理数字和小数部分
- 如果小数点的个数 > 1,则返回错误
- 如果小数点个数 <= 1,判断数字数量是否 > 0
- 处理指数部分
- 这时候,还要判断下如果有指数e时,小数点>1 或 数字数量为0,则错误
- 处理 + - 部分
- 处理数字部分
- 判断剩余部分
代码如下:
|
|
也可以用正则来实现
|
|
DFA
这里需要用到编译原理的知识,用状态机来解析一个个的token
状态机有两种
- 非确定的有限自动机(Nondeterministic Finite Automaton,NFA)
- 确定的有限自动机(Deterministic Finite Automaton,DFA)
NFA占用内存小,但是效率差些,会出现回溯
DFA占用内存大,但是效率高,不会有回溯
我们来构造出DFA状态机(可以根据正则表达式构造),如下图:
上图中橙色节点是终止状态,也就当字符串遍历完后,位于这个状态下,就表示正确结束,返回true
如果是处于蓝色节点,就是中间状态,返回false
这里初始状态为0,终止状态为2、4、7
如果输入的字符串是合法的,那么从0开始出发,不管中间怎么转换,当字符串遍历结束后,最终一定会落到状态2、4、7其中之一
之后,再根据状态机构造出跳转表,这个跳转表就等价于程序中用到的二维数组
跳转表如下:
| state | +- | 0-9 | . | eE | other |
|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | -1 | -1 |
| 1 | -1 | 2 | 3 | -1 | -1 |
| 2 | -1 | 2 | 4 | 5 | -1 |
| 3 | -1 | 4 | -1 | -1 | -1 |
| 4 | -1 | 4 | -1 | 5 | -1 |
| 5 | 6 | 7 | -1 | -1 | -1 |
| 6 | -1 | 7 | -1 | -1 | -1 |
| 7 | -1 | 7 | -1 | -1 | -1 |
上述表格中的0 - 7就对应了图中的各个状态
当在状态2时,遇到.就跳转到状态3,于是在表格中对应的行和列中填3
当状态3时,遇到0-9就跳转到状态4,于是在表格中对应的行和列中填4
将上述的表格保存为一个二维数组arr,第一列的state去掉
+-对应第0列、0-9对应第1、.对应底2列
eE对应底3列,其他字符对应底4列
然后根据当前状态,当前状态下的字符做跳转,比如:
- 当前状态
0,字符为.,也就是查找arr[0][3],跳转到状态3 - 当前状态
2,字符为8,查找arr[2][2],再次跳转到状态2
我们以-12.34E56来说明上述的跳转表是如何工作的
-对应第0列,arr[0][0] -> 状态 11对应第1列,arr[1][1] -> 状态 22对应第1列,arr[2][1] -> 状态 2.对应第2列,arr[2][2] -> 状态 43对应第1列,arr[4][1] -> 状态 44对应第1列,arr[4][1] -> 状态 4E对应第3列,arr[4][3] -> 状态 55对应第1列,arr[5][1] -> 状态 76对应第1列,arr[7][1] -> 状态 7- 字符串遍历结束,当前状态为
7,是终止状态,匹配成功
代码如下:
|
|