描述
请实现一个函数用来判断字符串str是否表示数值(包括科学计数法的数字,小数和整数)。
提示:
1.1 <= str.length <= 20
2.str 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。
3.如果怀疑用例是不是能表示为数值的,可以使用python的print(float(str))去查看。
官方题解:(1)https://blog.nowcoder.net/n/c05af3f3955d4cf08eade7073438b8c2?f=comment
(2)https://blog.nowcoder.net/n/c7b3aa6f22ae431fa6792a81ed8ca1b9?f=comment
- 正则表达式解法和异常捕获法,但可能不是面试官想要的答案。
- 这道题真正想考的是:有限状态自动机
先来看(1)的题解:
正则表达式,通过JZ52学习到了一定的正则表达式匹配之后,先来判断一下这道题是要判断字符串是否表示数值?
通过一些示例来看,我们大体可以将需要判断的条件归纳整理:
①是否有前后空格或者符号位?
②是否有整数?
③是否有小数点
④是否有指数e/E?
根据每个要点来进行判断,代码为:
match_Obj = re.match('^\s*[+-]{0,1}((\d)+((\.)(\d)+){0,1}|((\.)(\d)+)|((\d)+(\.)))([eE][+-]{0,1}[\d]+){0,1}\s*$',str)
首先是①的正则表达式,这里采用的是re.match()函数:表示必须从字符串开头匹配,先写出正则匹配字符串首尾的写法:
|
|
|
|
|
为了判断是否首尾有任意个空格字符的写法:
|
|
|
|
|
|
|
为了匹配前面是否有0到1个正负号的符号位写法:
|
|
|
|
|
|
|
|
然后是解决整数和小数点的正则表达式:
为了匹配0到1个前面包含1个数字(比如 100)【这句话不是很明白哎】或 数字+小数点+数字的字符(比如3.1416)的写法:
|
|
|
|
|
|
|
|
|
为了匹配1个或多个小数点 + 数字的字符(比如 .15)的写法:
|
|
|
|
|
|
|
|
|
|
为了匹配1个或多个数字+小数点的字符(比如 3.)的写法:
|
|
|
|
|
|
|
|
|
|
|
可以看出,匹配数字为(\d),小数点为(\.) 。蓝色括号为包含所有整数和小数点匹配情况。
最后解决是否有指数e/E的正则表达式?
|
|
|
|
|
|
|
|
|
|
|
|
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param str string字符串
# @return bool布尔型
import re
class Solution:
def isNumeric(self, str):
match_Obj = re.match('^\s*[+-]{0,1}((\d)+((\.)(\d)+){0,1}|((\.)(\d)+)|((\d)+(\.)))([eE][+-]{0,1}[\d]+){0,1}\s*$',str)
if match_Obj:
return True
else:
return False
异常捕获法:将字符串转换为浮点数,采用浮点数float() + try ...except 异常捕获的方法来判断字符串。
class Solution:
def isNumeric(self , str ):
# write code here
try:
float(str)
except:
return False
return True
再来看(2)的题解:有限状态自动机
先来了解一下有限状态自动机,大家叫它字符串匹配算法。https://blog.csdn.net/tyler_download/article/details/52549315
图中的两个圆圈叫节点,用于表示状态,这个图可以看成有两个状态分别是0和1。每个节点都有若干条边相连,当处于某个状态时,如果输入的字符跟该节点出发的某条边的内容一样,就会引起状态的转变。
状态机会有一个初始节点,和一个接收节点,以上图为例,我们可以设置初始节点为0,接收节点为1,当进行一系列的输入,使得状态机的状态不断变化,只要最后一个输入使得状态机处于接收节点,那么就表明当前输入可以被状态机接收。
根据字符类型和合法数值的特点,先定义状态。
字符类型:
空格 「 」、数字「 0—9 」 、正负号 「 +- 」 、小数点 「 .」 、幂符号 「 eE 」
状态定义:
按照字符串从左到右的顺序,定义以下 9 种状态。
1.开始的空格
2.幂符号前的正负号
3.小数点前的数字
4.小数点、小数点后的数字
5.当小数点前为空格时,小数点、小数点后的数字
6.幂符号
7.幂符号后的正负号
8.幂符号后的数字
9.结尾的空格结束状态:合法的结束状态有 2, 3, 7, 8
class Solution:
def isNumeric(self , str ):
# write code here
states = [
{ ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'
{ 'd': 2, '.': 4 } , # 1. 'sign' before 'e'
{ 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'
{ 'd': 3, 'e': 5, ' ': 8 }, # 3. 'digit' after 'dot'
{ 'd': 3 }, # 4. 'digit' after 'dot' (‘blank’ before 'dot')
{ 's': 6, 'd': 7 }, # 5. 'e'
{ 'd': 7 }, # 6. 'sign' after 'e'
{ 'd': 7, ' ': 8 }, # 7. 'digit' after 'e'
{ ' ': 8 } # 8. end with 'blank'
]
p = 0 # start with state 0
for c in str:
if '0' <= c <= '9': t = 'd' # digit elif c in "+-": t = 's' # sign elif c in "eE": t = 'e' # e&nbs***bsp;E elif c in ". ": t = c # dot, blank else: t = '?' # unknown if t not in states[p]: return False p = states[p][t] return p in (2, 3, 7, 8)
可是!牛客网提交有用例错误哎,等我再熟悉点再来改。