表示数值的字符串(Leetcode 剑指Offer20)

1

题目分析

   在某大厂的笔试中,我做过这道题目,不过当时的笔试较为简单,没有这个题目来的复杂。我们就来说一说这种判断是否合法的题目。

有限状态自动机

哇哦,名字就要起成我看不懂的样子,其实认真看下去也并不难,其主要是状态之间的来回转换。我们分析,合法的输入字符有哪些。
空格,符号,数字,小数点,e或者E。其他的都是不正确的输入。如果暴力if,当然也可以求解,在这里就不过多赘述,小伙伴们可以自行验证。
状态机,顾名思义,就是在状态之间来回转换,看一看能否到达最终的状态,如果可以则为有效输入,否则为无效输入。
下面在代码中对重要部分进行解读。
q

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class Solution:
def isNumber(self, s):
dic = [
# 起始状态为0,后面可以为空格" 1",正负号"-2",数字"3"或者小数点".4",其他的都是不合法的。
# 可以将起始处的空格定义为状态0,符号定义为状态1,数字定义为状态2,小数点定义为状态4。
{'blank': 0, 'sign': 1, 'digit': 2, 'dot': 4},
# 如果位于状态1,则为列表dic的索引1,出现了符号,后面可以为数字"-2",或者小数点"-.4",其他的都是不合法的。
# 数字已经定义了为状态2,小数点也定义了为状态4。
{'digit': 2, 'dot': 4},
# 如果位于状态2,则出现了数字,后面可以为数字"33",小数点"3.4",e"3e5",空格"3 ",其他的都是不合法的。
# 数字已经定义了为状态2,小数点定义为状态3,因为状态4为前面无数字的小数点,状态3则为前面有数字的小数点,e定义为状态5,空格定义为状态8
{'digit': 2, 'dot': 3, 'e': 5, 'blank': 8},
# 有的小朋友感觉困惑?为什么需要两个状态的小数点,因为前面有数字的小数点,后面还可以跟数字"34",e"3.e",或者直接结束"3."
{'digit': 3, 'e': 5, 'blank': 8},
# 而前面没有数字的小数点,后面只能够跟数字,因此两个小数点的状态是不同的,所以需要不同的记录方式,符号位,数字位,空格都是相同的道理。
{'digit': 3},
# 如果位于状态5,出现了e,那么后面可以跟符号"3e+5",或者数字"3e5"
# 符号定义为状态6,数字定义为状态7
{'sign': 6, 'digit': 7},
# 如果位于状态6,出现了符号,那么后面只能跟数字"3e+5"
# 数字定义为状态7
{'digit': 7},
# 如果位于状态7,出现了数字,那么后面可以跟数字"3e44",或者空格"3e4 "
# 数字定义为状态7,空格定义为状态8
{'digit': 7, 'blank': 8},
# 如果位于状态8,出现了空格,那么代表结束,只能跟空格
{'blank': 8}
]

# 设置初始状态为0
p = 0
# 遍历所有的字符,进行状态的转化
for c in s:
if c == ' ':
state = 'blank'
elif c == '+' or c == '-':
state = 'sign'
elif c == '.':
state = 'dot'
elif c == 'e' or c == 'E':
state = 'e'
elif c.isdigit():
state = 'digit'
else:
state = 'ERROR'
# 如果下一个状态不在当前状态的表中,说明报错,则不可以表示
if state not in dic[p]:
return False
# 如果在则继续判断是否在下一个状态中。
p = dic[p][state]
# 最终的状态是位于2,3,7,8状态中的一个,即必须要以状态2的数字结尾,状态3的小数点结尾,状态7的数字结尾,状态8的空格结尾。
return p in {2, 3, 7, 8}

刷题总结

  在这个文章里,详细的给小伙伴们捋了一下有限状态自动机的使用情景,小伙伴们需要认真审视自己的状态表,千万不要遗漏情况,要记得考虑一个字符的多种使用情景需要分配多种状态,记得这些事情,小伙伴们再也不用担心使用繁杂的if语句了。

-------------本文结束感谢您的阅读-------------
0%