(89)剑指 Offer 20. 表示数值的字符串(leetcode)

题目链接:
https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/
难度:中等
剑指 Offer 20. 表示数值的字符串
	请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,
但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。

这个题 很迷 搞得我很迷。。。。
不过 确实是不会做 看完题目后 感觉有点熟悉 编译原理???然后题解 卧槽 真是! 有限状态自动机 嗯 我知道 也只是知道 之前学的全忘了。。。
具体描述 ->题解

class Solution {
    
    
public:
    // 十种状态 
    enum State {
    
    
        // 初始状态
        STATE_INITIAL,
        // 符号位
        STATE_INT_SIGN,
        // 整数
        STATE_INTEGER,
        // 小数点(左侧有整数))
        STATE_POINT,
        // 小数点(左侧无整数))
        STATE_POINT_WITHOUT_INT,
        // 小数部分
        STATE_FRACTION,
        // 指数字符 e
        STATE_EXP,
        // 指数符号
        STATE_EXP_SIGN,
        // 指数数字
        STATE_EXP_NUMBER,
        // 结束状态
        STATE_END,
    };
    // 改变状态的类型
    enum CharType {
    
    
        // 数字
        CHAR_NUMBER,
        // 指数e
        CHAR_EXP,
        // 小数点
        CHAR_POINT,
        // 符号(+ -)
        CHAR_SIGN,
        // 空格
        CHAR_SPACE,
        // 非法
        CHAR_ILLEGAL,
    };
    // 返回字符类型 CharType 
    CharType getCharType(char s) {
    
    
        if (s >= '0' && s<= '9') {
    
    
            return CHAR_NUMBER;
        } else if (s == 'e' || s == 'E') {
    
    
            return CHAR_EXP;
        } else if (s == '.') {
    
    
            return CHAR_POINT;
        } else if (s == '+' || s == '-') {
    
    
            return CHAR_SIGN;
        } else if (s == ' ') {
    
    
            return CHAR_SPACE;
        } else {
    
    
            return CHAR_ILLEGAL;
        }
    }

    bool isNumber(string s) {
    
    
        // 看图
        unordered_map<State, unordered_map<CharType, State>> transfer{
    
    
            {
    
    
                STATE_INITIAL, {
    
    
                    {
    
    CHAR_SPACE, STATE_INITIAL},
                    {
    
    CHAR_NUMBER, STATE_INTEGER},
                    {
    
    CHAR_POINT, STATE_POINT_WITHOUT_INT},
                    {
    
    CHAR_SIGN, STATE_INT_SIGN},
                }
            }, {
    
    
                STATE_INT_SIGN, {
    
    
                    {
    
    CHAR_NUMBER, STATE_INTEGER},
                    {
    
    CHAR_POINT, STATE_POINT_WITHOUT_INT},
                }
            }, {
    
    
                STATE_INTEGER, {
    
    
                    {
    
    CHAR_NUMBER, STATE_INTEGER},
                    {
    
    CHAR_EXP, STATE_EXP},
                    {
    
    CHAR_POINT, STATE_POINT},
                    {
    
    CHAR_SPACE, STATE_END},
                }
            }, {
    
    
                STATE_POINT, {
    
    
                    {
    
    CHAR_NUMBER, STATE_FRACTION},
                    {
    
    CHAR_EXP, STATE_EXP},
                    {
    
    CHAR_SPACE, STATE_END},
                }
            }, {
    
    
                STATE_POINT_WITHOUT_INT, {
    
    
                    {
    
    CHAR_NUMBER, STATE_FRACTION},
                }
            }, {
    
    
                STATE_FRACTION,
                {
    
    
                    {
    
    CHAR_NUMBER, STATE_FRACTION},
                    {
    
    CHAR_EXP, STATE_EXP},
                    {
    
    CHAR_SPACE, STATE_END},
                }
            }, {
    
    
                STATE_EXP,
                {
    
    
                    {
    
    CHAR_NUMBER, STATE_EXP_NUMBER},
                    {
    
    CHAR_SIGN, STATE_EXP_SIGN},
                }
            }, {
    
    
                STATE_EXP_SIGN, {
    
    
                    {
    
    CHAR_NUMBER, STATE_EXP_NUMBER},
                }
            }, {
    
    
                STATE_EXP_NUMBER, {
    
    
                    {
    
    CHAR_NUMBER, STATE_EXP_NUMBER},
                    {
    
    CHAR_SPACE, STATE_END},
                }
            }, {
    
    
                STATE_END, {
    
    
                    {
    
    CHAR_SPACE, STATE_END},
                }
            }
        };
        int n=s.size();
        State state = STATE_INITIAL;
        for(int i=0;i<n;++i){
    
    
            CharType chartype=getCharType(s[i]);
            if(transfer[state].find(chartype)==transfer[state].end()){
    
    
                return false;
            }else{
    
    
                state=transfer[state][chartype];

            }
        }
        return state == STATE_INTEGER || state == STATE_POINT || state == STATE_FRACTION || state == STATE_EXP_NUMBER || state == STATE_END;
    }
};

还有种思路 只要你清楚所有数的规则就可以了 直接进行判断 只不过有点繁琐 (看的别人的思路。。。) 我是不太熟悉的

class Solution {
    
    
public:
    bool judgeLeft(string s){
    
    
        if(s.empty()){
    
    
            return false;
        }
        // 去除正负号
        if(s[0]=='+'||s[0]=='-'){
    
    
            s.erase(0, 1);
        }
        // flag记录是否有一个小数点
        bool flag = false;
        for(int i = 0; i < s.size(); ++i){
    
    
            if(isdigit(s[i])){
    
    
                continue;
            }
            if(s[i]=='.'){
    
    
                if(flag){
    
    
                    //有多个小数点,返回false
                    return false;
                }
                flag=true;
            }else{
    
    
                return false;
            }
        }
        return !s.empty()&&s!= ".";
    }

    bool judgeRight(string s){
    
    
        if(s.empty()){
    
    
            return false;
        }
        if(s[0]=='+'||s[0]=='-'){
    
    
            s.erase(0, 1);
        } 
        //右边不能出现小数点
        for(int i=0;i<s.size();++i){
    
    
            if(!isdigit(s[i])){
    
    
                return false;
            }
        }
        return !s.empty();
    }

    bool isNumber(string s) {
    
    
        // 去除首位空格 start
        //第一个不是空格的位置
        auto i=s.find_first_not_of(' ');
        if(i==string::npos){
    
    
            return false;
        }
        //最后一个不是空格的位置
        auto j=s.find_last_not_of(' ');
        //去除首尾空格
        s=s.substr(i,j-i+1);
        // 去除首位空格 end
        // 去除空格后s为空 false
        if(s.empty()){
    
    
            return false;
        }
        // 找到指数e
        auto k=s.find_first_of('E');
        if(k!=string::npos){
    
    
            s[k] = 'e';
        }
        auto pos=s.find('e');
        // 
        if(pos==string::npos){
    
    
            return judgeLeft(s);
        }
        return judgeLeft(s.substr(0,pos))&&judgeRight(s.substr(pos+1));
    }
};

猜你喜欢

转载自blog.csdn.net/li_qw_er/article/details/108365014