「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
题目
链接:leetcode-cn.com/problems/va…
有效数字(按顺序)可以分成以下几个部分:
- 一个 小数 或者 整数
- (可选)一个
'e'或'E',后面跟着一个 整数
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'或'-') - 下述格式之一:
- 至少一位数字,后面跟着一个点
'.' - 至少一位数字,后面跟着一个点
'.',后面再跟着至少一位数字 - 一个点
'.',后面跟着至少一位数字
- 至少一位数字,后面跟着一个点
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(
'+'或'-') - 至少一位数字
部分有效数字列举如下:
["2", "0089", "-0.1", "+3.14", "4.", "-.9", "2e10", "-90E3", "3e+7", "+6e-1", "53.5e93", "-123.456e789"]
部分无效数字列举如下:
["abc", "1a", "1e", "e3", "99e2.5", "--6", "-+3", "95a54e53"]
给你一个字符串 s ,如果 s 是一个 有效数字 ,请返回 true 。
示例 1:
输入: s = "0" 输出: true
示例 2:
输入: s = "e" 输出: false
示例 3:
输入: s = "." 输出: false
示例 4:
输入: s = ".1" 输出: true
提示:
1 <= s.length <= 20s仅含英文字母(大写和小写),数字(0-9),加号'+',减号'-',或者点'.'。
解题思路
如图所示:根据当前字符上下文拼接情况,会呈现不同的状态;
所有的字符串刚进来都是状态 0 的位置,接下来的字符串逐个拼接会走到不同的状态,最终走到红色位置即为true,否则为false;
我们来一步一步分析一下 状态变换过程;
首先进来状态为0
0 接 +/- 到 1
0 接 . 到 2
1 接 0-9 到 6
1 接 . 到 2
以此类推,每个状态后面只能接固定的几类字符,路断了即表示false了;
代码
/**
* @param {string} s
* @return {boolean}
*/
var isNumber = function(s) {
/*
blank 空格
sign + -
digit 0-9
e e
. .
*/
const graph = {
0:{ 'blank': 0, 'sign': 1, '.': 2, 'digit': 6 },
1:{ 'digit': 6, '.': 2 },
2:{ 'digit': 3 },
3:{ 'digit': 3, 'e': 4 },
4:{ 'digit': 5, 'sign': 7 },
5:{ 'digit': 5 },
6:{ 'digit': 6, '.': 3, 'e': 4 },
7:{ 'digit': 5 },
}
let state = 0;
// 空格不影响状态
for (let c of s.trim()) {
if (c >= '0' && c <= '9') {
c = 'digit';
} else if (c === ' ') {
c = 'blank';
} else if(c === '+' || c === '-') {
c = 'sign'
}
state = graph[state][c];
// 如果得到的状态为undefind说明不在可用字符范围,直接返回false
if (state === undefined) {
return false;
}
}
if (state == 3 || state == 5 || state == 6) {
return true;
}
return false;
};