[leetcode] 66.有效数字

126 阅读1分钟

题目描述

判断一个数字是否有效,可以分为以下几部分:

  1. 是一个小数或者整数
  2. (可选)存在e或者E,后面跟着一个数字

小数时:

  1. (可选)一个符号位'+'或者'-'
  2. 下列格式之一
    1. 至少一位数字,跟着一个'.'
    2. 至少一位数字,跟着一个'.',后面至少跟着一位数字
    3. 一个'.',后面跟着一位数字。

整数时:

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

思路:状态机

那**+12.34e+3**来举例,可以知道存在以下状态和转移路线

状态

  1. 初始状态
  2. 符号状态
  3. 数字状态
  4. 左边有小数点状态
  5. 左边无小数点状态
  6. 小数部分
  7. e
  8. 指数符号
  9. 指数数字

输入类型 0. 符号

  1. 数字
  2. e
  3. 其他

转移方程如下

0:in符号->1,in数字->2,in点->4

1:in数字->2,in点->4,ine->6

2:in数字->2,in点->3,ine->6

3:in数字->5,ine->6

4:in数字->5

5:in数字->5,ine->6

6:in符号->7,in数字->8

7:in数字->8

8:in数字->8

输入其他:错误状态

最终的有效状态:2,3,5,8

代码实现

class Solution {
private:
    enum State{
        STATE_INITLAL,
        STATE_SYMBOL,
        STATE_INT,
        STATE_POINT_LEFT_WITH_INT,
        STATE_POINT_LEFT_WITHOUT_INT,
        STATE_FRATCTION,
        STATE_EXP,
        STATE_EXP_SYMBOL,
        STATE_EXP_INT
    };
    enum CharType{
        CHARTYPE_SYMBOL,
        CHARTYPE_INT,
        CHARTYPE_POINT,
        CHARTYPE_E,
        CHARTYPE_ERROR,
    };
    CharType char_type(char c){
        if(c >= '0' && c <= '9'){
            return CHARTYPE_INT;
        } else if(c == '+' || c== '-'){
            return CHARTYPE_SYMBOL;
        } else if(c == 'e' || c == 'E'){
            return CHARTYPE_E;
        } else if (c == '.'){
            return CHARTYPE_POINT;
        } else {
            return CHARTYPE_ERROR;
        }
    }
public:
 unordered_map<State, unordered_map<CharType, State>> transf{
            {
                STATE_INITLAL,{
                    {CHARTYPE_SYMBOL, STATE_SYMBOL},
                    {CHARTYPE_INT, STATE_INT},
                    {CHARTYPE_POINT, STATE_POINT_LEFT_WITHOUT_INT}
                }
            },
            {
                STATE_SYMBOL,{
                    {CHARTYPE_INT, STATE_INT},
                    {CHARTYPE_POINT, STATE_POINT_LEFT_WITHOUT_INT}
                }
            },
            {
                STATE_INT,{
                    {CHARTYPE_INT,STATE_INT},
                    {CHARTYPE_POINT, STATE_POINT_LEFT_WITH_INT},
                    {CHARTYPE_E, STATE_EXP}
                }
            },
            {
                STATE_POINT_LEFT_WITH_INT,{
                    {CHARTYPE_INT, STATE_FRATCTION},
                    {CHARTYPE_E, STATE_EXP}
                }
            },
            {
                STATE_POINT_LEFT_WITHOUT_INT,{
                    {CHARTYPE_INT, STATE_FRATCTION}
                }
            },
            {
                STATE_FRATCTION,{
                    {CHARTYPE_INT, STATE_FRATCTION},
                    {CHARTYPE_E, STATE_EXP}
                }
            },
            {
                STATE_EXP,{
                    {CHARTYPE_SYMBOL, STATE_EXP_SYMBOL},
                    {CHARTYPE_INT, STATE_EXP_INT}
                }
            },
            {
                STATE_EXP_SYMBOL,{
                    {CHARTYPE_INT, STATE_EXP_INT}
                }
            },
            {
                STATE_EXP_INT,
                {
                    {CHARTYPE_INT, STATE_EXP_INT}
                }
            }
    };
    unordered_set<State> valid{STATE_INT, STATE_POINT_LEFT_WITH_INT, STATE_FRATCTION, STATE_EXP_INT};
    bool isNumber(string s) {
        State state = STATE_INITLAL;
        for(auto c : s){
            CharType type = char_type(c);
            if(transf[state].find(type) == transf[state].end()){
                return false;
            }
            state = transf[state][type];
        }
        return valid.find(state) != valid.end();
    }
       
};