【LeetCode】面试题20. 表示数值的字符串
题目:
思路:
1、分析规律,逻辑判断,需要特别注意特殊情况。
2、确定有限自动机(DFA)。构造DFA可以先写正则表达式再转换成DFA,也可以直接写。如下图所示DFA中红色为终止状态,蓝色为中间状态。DFA从状态0开始接收字符,当输入字符结束时当前状态处于中间状态,则拒绝;如果到达终止状态,则接受。状态0和8用于处理开始和结束时的空格。
红色的3个终止状态分别表示小数点前的数字、小数点后的数字、e后的数字。同样都是数字但是位置不同,不是一个状态。比如小数点前的数字可以转移到小数点,但是小数点后的数字无法转移到小数点。
' ' | '+/-' | '0-9' | '.' | 'e/E' | other | |
---|---|---|---|---|---|---|
0 | 0 | 1 | 6 | 2 | -1 | -1 |
1 | -1 | -1 | 6 | 2 | -1 | -1 |
2 | -1 | -1 | 3 | -1 | -1 | -1 |
3 | 8 | -1 | 3 | -1 | 4 | -1 |
4 | -1 | 7 | 5 | -1 | -1 | -1 |
5 | 8 | -1 | 5 | -1 | -1 | -1 |
6 | 8 | -1 | 6 | 3 | 4 | -1 |
7 | -1 | -1 | 5 | -1 | -1 | -1 |
8 | 8 | -1 | -1 | -1 | -1 | -1 |
代码:
Python
class Solution(object):
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
point = -1
e = -1
s = s.strip(' ')
if len(s) == 0:
return False
firstNum = -1
for i in range(len(s)):
# +/-只能出现在第一个字符或e之后, 但不能是最后一个字符
if s[i] in ['+', '-']:
if (i != 0 and s[i-1] not in ['e', 'E']) or i == len(s) - 1:
return False
elif s[i] == '.':
# .前面出现过.||.前没有数字且是最后一个字符, False
if point != -1 or (firstNum == -1 and i == len(s) - 1):
return False
else:
point = i
elif s[i] in ['e', 'E']:
# e是第一个或最后一个字符||e前面出现过e||e前面没有数字, False
if i == 0 or i == len(s) - 1 or e != -1 or firstNum == -1:
return False
# 出现过e, 且e之后不能出现.
else:
e = i
point = i
elif '0' <= s[i] <= '9':
if firstNum == -1:
firstNum = i
continue
else:
return False
return True
class Solution(object):
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
numSeen = False
dotSeen = False
eSeen = False
# 去掉前后的空格
s = s.strip(' ')
if len(s) == 0:
return False
for i in range(len(s)):
if '0' <= s[i] <= '9':
numSeen = True
# .之前不能出现.和e
elif s[i] == '.':
if dotSeen or eSeen:
return False
else:
dotSeen = True
# e之前不能出现e, 且必须出现数字
elif s[i] in ['e', 'E']:
if eSeen or not numSeen:
return False
else:
eSeen = True
numSeen = False # e之后也要出现数字
elif s[i] in ['-', '+']:
if i != 0 and s[i-1] not in ['e', 'E']:
return False
else:
return False
return numSeen
class Solution(object):
def getIndex(self, c):
myIndex = {
' ': 0,
'+': 1,
'-': 1,
'num': 2,
'.': 3,
'e': 4,
'E': 4}
if '0' <= c <= '9':
return myIndex.get('num')
else:
return myIndex.get(c, -1)
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
state = 0
finals = 0b101101000 # 终止状态3/5/6/8
transfer = [
[0, 1, 6, 2, -1],
[-1, -1, 6, 2, -1],
[-1, -1, 3, -1, -1],
[8, -1, 3, -1, 4],
[-1, 7, 5, -1, -1],
[8, -1, 5, -1, -1],
[8, -1, 6, 3, 4],
[-1, -1, 5, -1, -1],
[8, -1, -1, -1, -1]]
for c in s:
id = self.getIndex(c)
if id < 0:
return False
state = transfer[state][id]
if state < 0:
return False
# 1 << state表示1向左移动state位
return (finals & (1 << state)) > 0