题目描述

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串”+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里可以直接利用好已有函数

  1. /**
  2. * @param {string} s
  3. * @return {boolean}
  4. */
  5. var isNumber = function(s) {
  6. // 记得判定好纯空格字符串就行
  7. return !isNaN(s * 1) && s.split(' ').join('') !== '';
  8. };

也可以用有限状态自动机,本质是列举出遇到怎么样的字符,提前分析和配置好转移的状态,然后逐个字符判定转移就行了。

分析下状态:

+100.12e-3

  1. (frontBlank) 最开始的状态,遇到空格转移本状态,遇到 +- 转移 afterFrontSign,遇到数字转移 afterFrontNum,遇到小数点转 afterDot ;
  2. (afterFrontSign) 在前面符号之后,遇到数字转移 afterFrontNum ;
  3. (afterFrontNum) 在前面符号拼接数字后,遇到数字转移本状态,遇到小数点转 afterDot,遇到 eE 转 afterE,遇到空格转 endBlank ;
  4. (afterDot) 在小数点后,遇到数字转 afterDotNum ;
  5. (afterDotNum) 在小数点拼接数字后,遇到数字转本状态,遇到 eE 转 afterE, 遇到空格转 endBlank ;
  6. (afterE) 在 eE之后,遇到符号转 afterESign,遇到数字转 afterENum ;
  7. (afterESign) 在 eE 拼接+-符号之后,遇到数字转 afterENum ;
  8. (afterENum) 在 eE 符号拼接数字后,遇到数字转本状态,遇到空格转 endBlank;
  9. (endBlank) 在最后空格,遇到空格转本状态。
  1. /**
  2. * @param {string} s
  3. * @return {boolean}
  4. */
  5. var isNumber = function(s) {
  6. const state = {
  7. frontBlank: { // 最开始的状态
  8. blank: 'frontBlank', // 遇到空格转移本状态
  9. sign: 'afterFrontSign', // 遇到 +- 转移 afterFrontSign
  10. num: 'afterFrontNum', // 遇到数字转移 afterFrontNum
  11. dot: 'afterDot' // 遇到小数点转 afterDot
  12. },
  13. afterFrontSign: { // 在前面符号之后
  14. num: 'afterFrontNum', // 遇到数字转移 afterFrontNum
  15. dot: 'afterDot' // 遇到小数点转 afterDot
  16. },
  17. afterFrontNum: { // 在前面符号拼接数字后
  18. num: 'afterFrontNum', // 遇到数字转移本状态
  19. dot: 'dotAfterNum', // 遇到小数点转 dotAfterNum
  20. e: 'afterE', // 遇到 eE 转 afterE
  21. blank: 'endBlank' // 遇到空格转 endBlank
  22. },
  23. dotAfterNum: { // 小数点前有数字的
  24. num: 'afterDotNum', // 遇到数字转 afterDotNum,
  25. blank: 'endBlank', // 遇到空格转 endBlank
  26. e: 'afterE', // 遇到 eE 转 afterE
  27. },
  28. afterDot: { // 小数点前没有数字的
  29. num: 'afterDotNum' // 遇到数字转 afterDotNum
  30. },
  31. afterDotNum: { // 在小数点拼接数字后
  32. num: 'afterDotNum', // 遇到数字转移本状态
  33. e: 'afterE', // 遇到 eE 转 afterE
  34. blank: 'endBlank' // 遇到空格转 endBlank
  35. },
  36. afterE: { // 在 eE之后
  37. sign: 'afterESign', // 遇到符号转 afterESign
  38. num: 'afterENum' // 遇到数字转 afterENum
  39. },
  40. afterESign: { // 在 eE 拼接+-符号之后
  41. num: 'afterENum' // 遇到数字转 afterENum
  42. },
  43. afterENum: { // 在 eE 符号拼接数字后
  44. num: 'afterENum', // 遇到数字转本状态
  45. blank: 'endBlank' // 遇到空格转 endBlank
  46. },
  47. endBlank: { // 在最后空格
  48. blank: 'endBlank' // 遇到空格转本状态
  49. }
  50. };
  51. const charSet = {
  52. ' ': 'blank',
  53. '+': 'sign',
  54. '-': 'sign',
  55. '.': 'dot',
  56. 'e': 'e',
  57. 'E': 'e',
  58. '0': 'num',
  59. '1': 'num',
  60. '2': 'num',
  61. '3': 'num',
  62. '4': 'num',
  63. '5': 'num',
  64. '6': 'num',
  65. '7': 'num',
  66. '8': 'num',
  67. '9': 'num',
  68. };
  69. let nowState = 'frontBlank';
  70. let normalState = ['afterFrontNum', 'dotAfterNum', 'afterDotNum', 'afterENum', 'endBlank'];
  71. for (let i = 0; i < s.length; i++) {
  72. let char = charSet[s[i]];
  73. // console.log(`char[${char}], nowState[${nowState}], state[nowState][char]: ${state[nowState][char]}`);
  74. nowState = state[nowState][char];
  75. if (!nowState) {
  76. return false;
  77. }
  78. }
  79. // console.log(`nowState[${nowState}]`);
  80. return normalState.indexOf(nowState) >= 0;
  81. };

看简写版的: https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/solution/mian-shi-ti-20-biao-shi-shu-zhi-de-zi-fu-chuan-y-2/

  1. class Solution:
  2. def isNumber(self, s: str) -> bool:
  3. states = [
  4. { ' ': 0, 's': 1, 'd': 2, '.': 4 }, # 0. start with 'blank'
  5. { 'd': 2, '.': 4 } , # 1. 'sign' before 'e'
  6. { 'd': 2, '.': 3, 'e': 5, ' ': 8 }, # 2. 'digit' before 'dot'
  7. { 'd': 3, 'e': 5, ' ': 8 }, # 3. 'digit' after 'dot'
  8. { 'd': 3 }, # 4. 'digit' after 'dot' (‘blank’ before 'dot')
  9. { 's': 6, 'd': 7 }, # 5. 'e'
  10. { 'd': 7 }, # 6. 'sign' after 'e'
  11. { 'd': 7, ' ': 8 }, # 7. 'digit' after 'e'
  12. { ' ': 8 } # 8. end with 'blank'
  13. ]
  14. p = 0 # start with state 0
  15. for c in s:
  16. if '0' <= c <= '9': t = 'd' # digit
  17. elif c in "+-": t = 's' # sign
  18. elif c in "eE": t = 'e' # e or E
  19. elif c in ". ": t = c # dot, blank
  20. else: t = '?' # unknown
  21. if t not in states[p]: return False
  22. p = states[p][t]
  23. return p in (2, 3, 7, 8)