题⽬描述

请实现⼀个函数⽤来判断字符串str是否表示数值(包括科学计数法的数字,⼩数和整数)。科学计数法的数字(按顺序)可以分成以下⼏个部分:

  1. 若⼲空格

  2. ⼀个整数或者⼩数

  3. (可选)⼀个 ’ e ’ 或 ’ E ‘,后⾯跟着⼀个整数(可正可负)

  4. 若⼲空格

⼩数(按顺序)可以分成以下⼏个部分:

  1. 若⼲空格

  2. (可选)⼀个符号字符(’+’ 或 ‘-’)

  3. 可能是以下描述格式之⼀:

  4. ⾄少⼀位数字,后⾯跟着⼀个点 ‘.’

  5. ⾄少⼀位数字,后⾯跟着⼀个点 ‘.’,后⾯再跟着⾄少⼀位数字

  6. ⼀个点 ‘.’,后⾯跟着⾄少⼀位数字

  7. 若⼲空格

整数(按顺序)可以分成以下⼏个部分:

  1. 若⼲空格

  2. (可选)⼀个符号字符(’ + ’ 或 ’ - ‘)

  3. ⾄少⼀位数字

  4. 若⼲空格

例如,字符串["+100",“5e2”,"-123",“3.1416”,"-1E-16"] 都表示数值。

但是[“12e”,“1a3.14”,“1.2.3”,"+-5",“12e+4.3”] 都不是数值。

提示:

  1. 1 <= str.length <= 25

  2. str 仅含英⽂字⺟(⼤写和⼩写),数字(0-9),加号 ‘+’,减号 ‘-’,空格 ’ ’ 或者点 ‘.’ 。

  3. 如果怀疑⽤例是不是能表示为数值的,可以使⽤python 的print(float(str)) 去查看

示例1 输⼊:“123.45e+6” 返回值:true

示例2 输⼊:“1.2.3” 返回值:false

思路及解答

暴力分析拆解

主要是分析好判断分⽀,可以定义⼏个变量:

  • hashNum : 是否已经有数字

  • hashE :是否已经有E

  • hasSign :是否已经有符号

  • hasDot :是否已经有⼩数点

⾸先,初始化当前的索引index =0,字符串头部的空格需要跳过。

  • 循环判断索引是否在有效的范围内:

    • 循环判断是否是数字,是数字则更新hasNum = true ,并且索引后移,直到不是数字的时候,跳出循环。
  • 跳出循环后,需要判断当前的index 是否合法,不合法直接break

  • 取出当前索引的字符c :

    • 如果c 是e 或者E :

      • 如果前⾯已经出现过E,或者前⾯没有数字,直接返回false

      • 否则, hasE 置为true,其他的置为false,也就是E后⾯可以继续出现符号数字和⼩数点了

    • 如果c 是“ + ”或者“ - ”:

      • 前⾯如果已经出现过数字或者符号或者⼩数点,都不是合法的

      • 否则hasSign 置为true,表示符号出现过

    • 如果c 是⼩数点“ . ”

      • 如果前⾯已经有⼩数点或者有E出现了,那么就是⾮法的,返回false

      • 否则hasDot 置为true

    • 如果c 为空格,直接跳出循环

    • 否则,直接返回false

  • 最后也需要跳过空格

  • 最后判断是否合法的条件是:是否到达最后⼀个字符,并且出现过数字

这道题,其实本质是状态的切换,最最重要的⼀点,是 E 出现之后,其实⼩数点和符号,和数字,都是可以再出现的,可以理解为 E 就是⼀个分割线。

正则表达式

直接借助正则表达式进⾏匹配,但是并不太推荐这种解法:

  • O(n)时间复杂度

  • O(1)空间复杂度

有限状态机

使用确定有限状态机(DFA)来精确建模数值的判断过程。

有限状态机法:通过状态转移精确控制数值格式。定义9种状态,根据输入字符进行状态转移

  • 时间复杂度:O(n)

  • 空间复杂度:O(1)