剑指 Offer 20. 表示数值的字符串

剑指 Offer 20. 表示数值的字符串

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。

数值(按顺序)可以分成以下几个部分:

若干空格
一个 小数 或者 整数
(可选)一个 'e' 或 'E' ,后面跟着一个 整数
若干空格

小数(按顺序)可以分成以下几个部分:

(可选)一个符号字符('+' 或 '-')
下述格式之一:
    至少一位数字,后面跟着一个点 '.'
    至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
    一个点 '.' ,后面跟着至少一位数字

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

(可选)一个符号字符('+' 或 '-')
至少一位数字

部分数值列举如下:

["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]

部分非数值列举如下:

["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]

示例 1:

输入:s = “0”
输出:true

示例 2:

输入:s = “e”
输出:false

示例 3:

输入:s = “.”
输出:false

示例 4:

输入:s = " .1 "
输出:true

提示:

1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。

解题思路 : 哈希表+有限状态机

对于一个要表示数值的有固定格式的字符串,显然每个字符的取值不外乎以下几种有限的状态

  1. 开头的空格
  2. e/E之前的符号位
  3. 前面有数字的小数点
  4. 小数点前的数字
  5. 小数点后的数字
  6. e、E
  7. e之后的符号位
  8. e之后的数字
  9. 结束的空格
  10. 前面没有数字的小数点

构建的有限状态机如下

在这里插入图片描述

​ 对于遍历的每一个字符,都设定好其可能的下一步状态,如果下一个字符不属于这个状态,返回false,直到遍历完成。如果最终状态是3、4、5、8、9状态是正确的,返回true,否则返回false

代码

class Solution {
    public boolean isNumber(String s) {
        Map[] maps = {
            new HashMap(){{put(' ',0);put('s',1);put('p',9);put('n',3);}},
            new HashMap(){{put('p',9);put('n',3);}},
            new HashMap(){{put('n',4);put(' ',8);put('e',5);}},
            new HashMap(){{put('n',3);put('p',2);put('e',5);put(' ',8);}},
            new HashMap(){{put('n',4);put('e',5);put(' ',8);}},
            new HashMap(){{put('s',6);put('n',7);}},
            new HashMap(){{put('n',7);}},
            new HashMap(){{put('n',7);put(' ',8);}},
            new HashMap(){{put(' ',8);}},
            new HashMap(){{put('n',4);}}
        };
        int i = 0 ;
        char flag = ' ';
        for(char c : s.toCharArray())
        {
            if(c>='0'&&c<='9')
            {
                flag = 'n';
            }else if(c==' ')
            {
                flag = ' ';
            }else if(c=='.')
            {
                flag = 'p';
            }else if(c=='+'||c=='-')
            {
                flag = 's';
            }else if(c=='e'||c=='E')
            {
                flag = 'e';
            }else{
                return false;
            }
            if(!maps[i].containsKey(flag)) return false;
            i = (int)maps[i].get(flag);
        }
        return i==3||i==4||i==7||i==8||i==2;
    }
}

算法执行过程

  1. 初始化
    1. 状态转移映射 map[] , i 表示第i+1个状态,map[i]表示第i个状态的合法下一个状态的集合,形式为键值对 <Character,Integer> ,输入标识符,返回下一个状态
    2. 当前状态 i : 初始状态初始化为i=0,表示第一个状态(开头空格)
  2. 状态转移循环
    1. 记录字符类型 : 字符flag为下一个字符所表示的状态,分为以下6种情况:
      1. 字符c>‘0’&&flag<‘9’ , flag = ‘n’(number)
      2. 字符c==’ ’ , flag = ’ ’
      3. 字符c==’.’ , flag = ‘p’(point)
      4. 字符c== ‘+’ ||c == ‘-’ , flag = ‘s’(signal)
      5. 字符c== ‘e’ || c== ‘E’ , flag = ‘e’
      6. 其他直接返回false
    2. 终止条件 : 如果flag不在 哈希映射表map中,则说明无法转移到下一个状态,直接返回false
    3. 返回值 : 跳出循环之后,如果状态 i == 2、3、4、7、8,则说明结果合法,返回true
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值