题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+100”、”5e2”、”-123”、”3.1416”、”-1E-16”、”0123”都表示数值,但”12e”、”1a3.14”、”1.2.3”、”+-5”及”12e+5.4”都不是。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
js里可以直接利用好已有函数
/*** @param {string} s* @return {boolean}*/var isNumber = function(s) {// 记得判定好纯空格字符串就行return !isNaN(s * 1) && s.split(' ').join('') !== '';};
也可以用有限状态自动机,本质是列举出遇到怎么样的字符,提前分析和配置好转移的状态,然后逐个字符判定转移就行了。
分析下状态:
+100.12e-3
- (frontBlank) 最开始的状态,遇到空格转移本状态,遇到 +- 转移 afterFrontSign,遇到数字转移 afterFrontNum,遇到小数点转 afterDot ;
- (afterFrontSign) 在前面符号之后,遇到数字转移 afterFrontNum ;
- (afterFrontNum) 在前面符号拼接数字后,遇到数字转移本状态,遇到小数点转 afterDot,遇到 eE 转 afterE,遇到空格转 endBlank ;
- (afterDot) 在小数点后,遇到数字转 afterDotNum ;
- (afterDotNum) 在小数点拼接数字后,遇到数字转本状态,遇到 eE 转 afterE, 遇到空格转 endBlank ;
- (afterE) 在 eE之后,遇到符号转 afterESign,遇到数字转 afterENum ;
- (afterESign) 在 eE 拼接+-符号之后,遇到数字转 afterENum ;
- (afterENum) 在 eE 符号拼接数字后,遇到数字转本状态,遇到空格转 endBlank;
- (endBlank) 在最后空格,遇到空格转本状态。
/*** @param {string} s* @return {boolean}*/var isNumber = function(s) {const state = {frontBlank: { // 最开始的状态blank: 'frontBlank', // 遇到空格转移本状态sign: 'afterFrontSign', // 遇到 +- 转移 afterFrontSignnum: 'afterFrontNum', // 遇到数字转移 afterFrontNumdot: 'afterDot' // 遇到小数点转 afterDot},afterFrontSign: { // 在前面符号之后num: 'afterFrontNum', // 遇到数字转移 afterFrontNumdot: 'afterDot' // 遇到小数点转 afterDot},afterFrontNum: { // 在前面符号拼接数字后num: 'afterFrontNum', // 遇到数字转移本状态dot: 'dotAfterNum', // 遇到小数点转 dotAfterNume: 'afterE', // 遇到 eE 转 afterEblank: 'endBlank' // 遇到空格转 endBlank},dotAfterNum: { // 小数点前有数字的num: 'afterDotNum', // 遇到数字转 afterDotNum,blank: 'endBlank', // 遇到空格转 endBlanke: 'afterE', // 遇到 eE 转 afterE},afterDot: { // 小数点前没有数字的num: 'afterDotNum' // 遇到数字转 afterDotNum},afterDotNum: { // 在小数点拼接数字后num: 'afterDotNum', // 遇到数字转移本状态e: 'afterE', // 遇到 eE 转 afterEblank: 'endBlank' // 遇到空格转 endBlank},afterE: { // 在 eE之后sign: 'afterESign', // 遇到符号转 afterESignnum: 'afterENum' // 遇到数字转 afterENum},afterESign: { // 在 eE 拼接+-符号之后num: 'afterENum' // 遇到数字转 afterENum},afterENum: { // 在 eE 符号拼接数字后num: 'afterENum', // 遇到数字转本状态blank: 'endBlank' // 遇到空格转 endBlank},endBlank: { // 在最后空格blank: 'endBlank' // 遇到空格转本状态}};const charSet = {' ': 'blank','+': 'sign','-': 'sign','.': 'dot','e': 'e','E': 'e','0': 'num','1': 'num','2': 'num','3': 'num','4': 'num','5': 'num','6': 'num','7': 'num','8': 'num','9': 'num',};let nowState = 'frontBlank';let normalState = ['afterFrontNum', 'dotAfterNum', 'afterDotNum', 'afterENum', 'endBlank'];for (let i = 0; i < s.length; i++) {let char = charSet[s[i]];// console.log(`char[${char}], nowState[${nowState}], state[nowState][char]: ${state[nowState][char]}`);nowState = state[nowState][char];if (!nowState) {return false;}}// console.log(`nowState[${nowState}]`);return normalState.indexOf(nowState) >= 0;};
class Solution:def isNumber(self, s: str) -> bool: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 0for c in s:if '0' <= c <= '9': t = 'd' # digitelif c in "+-": t = 's' # signelif c in "eE": t = 'e' # e or Eelif c in ". ": t = c # dot, blankelse: t = '?' # unknownif t not in states[p]: return Falsep = states[p][t]return p in (2, 3, 7, 8)
