请实现一个函数,用来判断一个字符串是否表示数值(包括科学计数法、小数和整数)。
科学计数法数字(按顺序)
可以分成以下几个部分:
- 若干空格
- 一个整数或者小数
- (可选)一个
e 或 E ,后面跟着一个整数(可正可负)
- 若干空格
小数(按顺序)
可以分成以下几个部分:
- 若干空格
- (可选)一个符号字符(
+ 或 -)
- 可能是以下描述格式之一:
- 至少一位数字,后面跟着一个点
.
- 至少一位数字,后面跟着一个点
. ,后面再跟着至少一位数字
- 一个点
. ,后面跟着至少一位数字
- 若干空格
整数(按顺序)
可以分成以下几个部分:
- 若干空格
- (可选)一个符号字符(
+ 或 -)
- 至少一位数字
- 若干空格
示例
- 例如,字符串
["+100", "5e2", "-123", "3.1416", "-1E-16"] 都表示数值。
- 但是
["12e", "1a3.14", "1.2.3", "±5", "12e+4.3"] 都不是数值。
提示
1 <= str.length <= 25
str 仅含英文字母(大写和小写),数字(0-9),加号 + ,减号 - ,空格 ` 或者点.` 。
- 如果怀疑用例是不是能表示为数值的,可以使用 Python 的
print(float(str)) 去查看。
进阶要求:时间复杂度 O(n),空间复杂度 O(n)。
Go 语言正则解法
如何用一个模式覆盖所有这些情况呢?在 Go 中,我们可以借助 regexp 标准库,用一条精心设计的正则表达式来解决这个问题。
package main
import "regexp"
func isNumeric( str string ) bool {
reg := regexp.MustCompile(`^\s*[+-]?((\d+(\.\d*)?)|(\.\d+))([eE][+-]?\d+)?\s*$`)
return reg.MatchString(str)
}
让我们来详细解析这个正则表达式的每一部分。
*`^\s`**
^ 表示匹配字符串的开始。
\s* 匹配 0 个或多个空白字符(空格、制表符等),对应规则中“若干空格”的要求。
[+-]?
- 匹配一个正号
+ 或负号 -。
? 表示这个符号是可选的,对应整数和小数规则中“(可选)一个符号字符”的部分。
*`((\d+(.\d)?)|(.\d+))** 这是核心部分,用于匹配整数或小数。它由两个用|` 分隔的子模式构成。
*子模式 1:`(\d+(.\d)?)`**
\d+:匹配一个或多个数字(\d 等价于 [0-9],+ 表示至少一个)。
(\.\d*)?:这是一个可选分组。
\. 匹配小数点字符 .。
\d* 匹配 0 个或多个数字。
- 这个子模式覆盖了以下情况:
123 (纯整数)
123. (整数部分加小数点,无小数位)
123.45 (标准小数)
子模式 2:(\.\d+)
\. 匹配小数点字符 .。
\d+ 匹配一个或多个数字。
- 这个子模式专门覆盖以小数点开头的小数,例如
.123。
([eE][+-]?\d+)?
- 这个整体用
? 包裹,表示科学计数法的指数部分是可选的。
[eE] 匹配字符 e 或 E。
[+-]? 同上,匹配可选的指数符号。
\d+ 匹配一个或多个数字作为指数值。
*`\s$`**
\s* 再次匹配 0 个或多个末尾空白字符。
$ 表示匹配字符串的结束。
总结
通过以上拆解,我们可以看到这条正则表达式严格遵循了题目中关于数值字符串的所有定义。它不仅能有效区分合法与非法的数值表示,而且实现简洁,满足了 O(n) 时间复杂度的要求。在处理字符串匹配与验证类 算法/数据结构 问题时,正则表达式往往能提供一种清晰高效的解决方案。如果你对这类问题感兴趣,想查看更多解题思路和代码实现,欢迎访问 云栈社区 的算法板块进行深入探讨和学习。
|