一、题目
验证给定的字符串是否可以解释为十进制数字。
例如:
"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% |