一、题目
验证给定的字符串是否可以解释为十进制数字。
例如:
"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
" -90e3 "
=> true
" 1e"
=> false
"e3"
=> false
" 6e-1"
=> true
" 99e2.5 "
=> false
"53.5e93"
=> true
" --6 "
=> false
"-+3"
=> false
"95a54e53"
=> false
说明:我们有意将问题陈述地比较模糊。在实现代码之前,你应当事先思考所有可能的情况。这里给出一份可能存在于有效十进制数字中的字符列表:
- 数字 0-9
- 指数 “e”
- 正/负号 “+”/“-“
- 小数点 “.”
当然,在输入中,这些字符的上下文也很重要。
更新于2015-02-10:
C++
函数的形式已经更新了。如果你仍然看见你的函数接收 const char *
类型的参数,请点击重载按钮重置你的代码。
二、思路
1. 正则
作为有效的十进制数字,必然是以+
、-
开头,+
号在数为非负的时候是可以不写的,所以可以得出正则表达式第一部分:^[+-]?
对于科学计数法,指数e
是在小数点后边的,所以接下来就是小数点问题:
- 例如:
.5
这个数,对应的正则表达式则是:\.\d+
- 例如:
5.
这个数,对应的正则表达式则是:\d+
- 例如:
4.5
这个数,对应正则表达式则是:\d+\.\d+
- 例如:
5
这个数,是没有小数点的,对应正则表达式是:\d+
- 所以,综合以上几种情况,第二部分的正则表达式为:
(\d+|\d+\.|\d+\.\d+|\.\d+)
接下来便是科学计数法部分了,因为指数e
不一定存在,所以正则表达式是:(e[+-]?\d+)?
。
到这里就结束了,所以整体的正则表达式是:^[+-]?(\d+|\d+\.|\d+\.\d+|\.\d+)(e[+-]?\d+)?$
2. 条件判断
对于这道题,通过题目所提供的信息,我们可以对以下几个条件进行判断:
- 首先就是
+
和-
,这两个符号出现的位置有两个:- 数字开头
- 指数
e
的后边,紧接着e
出现
- 接下来就是小数点了,并且小数点一定是在指数
e
的前边的。所以- 当前值为小数点的时候,
e
必须还没有出现过 - 小数点只能出现一次
- 当前值为小数点的时候,
- 接下来判断
e
,e
只能出现一次- 并且
e
的出现之前必须存在数字 e
出现一次以后。也必须有数字存在
根据上边的条件限定,我们假设字符串长度为n
(使用strip()
去掉两侧空格以后),当前元素下标为i
,接下来就该考虑在代码中的实现了。
对于+
、-
我们需要做的是对其位置进行判断:
- 第一种情况就是
i == 0
- 第二种情况就是
i != 0 and s[i] == 'e'
,如果s[i] != 'e'
,那么就可以返回False
接下来,小数点.
,我们就需要对小数点和指数e
的出现状态进行判断了。我们可以创建两个变量dot
、e
分别来保存它们的出现状态,初始值都设为False
,表示还没有出现。出现以后,值改为True
。
接下来就是e
,这时候需要判断的是e
的出现状态,以及num_pre_e
就是在e
之前是否有数字出现。以及num_after_e
也就是在e
之后是否有数字出现。并且在s[i] == 'e'
的时候,需要将num_after_e
的值重置为False
。
接下来,在判断s[i].isdigit() is True
的情况下,将num_after_e
的值重置为True
。并且,在e is Flase
的条件下,num_pre_e
的值才为True
。
三、代码
1. 正则
import re
class Solution:
def isNumber(self, s: str) -> bool:
pattern = re.compile(r'^[+-]?(\d+\.\d+|\d+\.|\.\d+|\d+)(e[+-]?\d+)?$')
res = pattern.findall(s.strip(' '))
return True if len(res) > 0 else False
2. 条件判断
# 点、指数e、e后边的数字、e前边的数字
dot, e, num_after_e, num_pre_e = False, False, False, False
s = s.strip(' ')
n = len(s)
for i in range(n):
if s[i] in ['+', '-']:
if i != 0 and s[i-1] != 'e':
return False
elif s[i] == '.':
if dot or e:
return False
else:
dot = True
elif s[i] == 'e':
if e or not num_pre_e:
return False
else:
e = True
num_after_e = False
elif s[i].isdigit():
if not e:
num_pre_e = True
num_after_e = True
else:
return False
return num_after_e and num_pre_e
四、表现
method | 运行时间 | 表现 | 内存消耗 | 表现 |
---|---|---|---|---|
1. 正则 | 48ms | 55.48% | 13.6MB | 5.03% |
2. 条件判断 | 48ms | 55.48% | 13.5MB | 10.19% |