剑指 Offer 20. 表示数值的字符串(C++) 有限状态自动机

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。

解题思路:

本题使用有限状态自动机。根据字符类型和合法数值的特点,先定义状态,再画出状态转移图,最后编写代码即可。
字符类型:
空格 「 」、数字「 0—9 」 、正负号 「 +− 」 、小数点 「 . 」 、幂符号 「 eE 」 。
状态定义:
按照字符串从左到右的顺序,定义以下 9 种状态。
0、开始的空格
1、幂符号前的正负号
2、小数点前的数字
3、小数点、小数点后的数字
4、当小数点前为空格时,小数点、小数点后的数字
5、幂符号
6、幂符号后的正负号
7、幂符号后的数字
8、结尾的空格
结束状态:
合法的结束状态有 2, 3, 7, 8 。

在这里插入图片描述

算法流程:

在这里插入图片描述

class Solution {
    
    
public:
    // 方法一:有限状态自动机DFA,时间复杂度 O(N)
    typedef pair<char,int> charint;
    typedef unordered_map<char,int> unmap;//重新定义数据类型
    bool isNumber(string s) {
    
    
        vector<unmap> states = {
    
    
            unmap{
    
    charint(' ',0),charint('s',1),charint('d',2),charint('.',4)},
            //states[0][' ']、states[1]['s']、states[2]['d']、states[3]['.']
            unmap{
    
    charint('d',2),charint('.',4)},
            unmap{
    
    charint('d',2),charint('.',3),charint('e',5),charint(' ',8)},
            unmap{
    
    charint('d',3),charint('e',5),charint(' ',8)},
            unmap{
    
    charint('d',3)},
            unmap{
    
    charint('s',6),charint('d',7)},
            unmap{
    
    charint('d',7)},
            unmap{
    
    charint('d',7),charint(' ',8)},
            unmap{
    
    charint(' ',8)}
        };
        int p = 0;
        char t;
        for(char c:s){
    
    
            if(c >= '0' && c <= '9')
                t = 'd';
            else if(c == '+' || c == '-')
                t = 's';
            else if(c == 'e' || c == 'E')
                t = 'e';
            else if(c == '.' || c == ' ')
                t = c;
            else
                t = '?';
            if(!states[p].count(t))//假如t不存在于states[p]中
                return false;
            p = (int) states[p][t];
        }
        return p == 2 || p == 3 || p == 7 || p == 8;
    }
};

可以简化为以下代码

class Solution {
    
    
public:
    // 方法一:有限状态自动机DFA,时间复杂度 O(N)
    typedef pair<char,int> charint;
    typedef unordered_map<char,int> unmap;//重新定义数据类型
    bool isNumber(string s) {
    
    
        vector<unmap> states = {
    
    
            {
    
    charint(' ',0),charint('s',1),charint('d',2),charint('.',4)},
            {
    
    charint('d',2),charint('.',4)},
            {
    
    charint('d',2),charint('.',3),charint('e',5),charint(' ',8)},
            {
    
    charint('d',3),charint('e',5),charint(' ',8)},
            {
    
    charint('d',3)},
            {
    
    charint('s',6),charint('d',7)},
            {
    
    charint('d',7)},
            {
    
    charint('d',7),charint(' ',8)},
            {
    
    charint(' ',8)}
        };
        int p = 0;
        char t;
        for(char c:s){
    
    
            if(c >= '0' && c <= '9')
                t = 'd';
            else if(c == '+' || c == '-')
                t = 's';
            else if(c == 'e' || c == 'E')
                t = 'e';
            else if(c == '.' || c == ' ')
                t = c;
            else
                t = '?';
            if(!states[p].count(t))
                return false;
            p = (int) states[p][t];
        }
        return p == 2 || p == 3 || p == 7 || p == 8;
    }
};

复杂度分析:

时间复杂度 O(N): 其中 N 为字符串 s 的长度,判断需遍历字符串,每轮状态转移的使用 O(1)时间。
空间复杂度 O(1) : states 和 p 使用常数大小的额外空间。

作者:jyd
链接: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/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/qq_30457077/article/details/114761090