• valid number 判断字符串是否为有效数字


    RT,面试题,给定一个字符串判断是否为科学计数法的有效数字。此题各种繁琐考虑。今天终于学会了用有限状态机来处理。理解之后简洁易懂。在此分享我的理解推导思路,大有收获啊

    网上有解法说先记录每个状态代表的意思,然后根据状态的可能转移写出转移矩阵。但是,你肯定是一头雾水,状态数一多,就混乱不堪,根本很难有耐心或者细心把状态数清楚并记录正确。

    现在我带你怎么较好的理解,最后发现我们最后可以根本不用知道每个状态时什么意思,只是按照填写规范写完即可。

    首先我们要知道,每次的输入有六种可能,分别是 无效字符invalid,空格space,正负号sign,数字digit,点dot,指数e或者E暂且记作eE

    那么第一次当然就是从状态0开始,状态0中之后的各种转移记录如下:

    状态0:

    如果来一个invalid,那么下次转移-1;(-1就是没有这个状态,那么就返回false)

    如果来一个space,那么还是和当前状态0一样的状态,所以转移至0;

    如果来一个sign,那么就要转移出去了,但是我们现在不知道有什么状态可以供它转移,先放着

    如果来一个digit,那么也要继续转移,但是还是不知道可以转到哪里,又放着

    如果来一个dot,同样要转移,因为(.0)也是合法数字,但是还是不知道有什么状态可以转,放着

    如果来一个eE,一开始就是eE,就是不合法了,因为eE前面一定要有数字,所以这个时候确定转移至-1,也就是要false了。

    我们用图来标记如下:

    状态0:

    invalid -> -1

    space -> 0

    sign -> ?    ----->   之后考虑状态1后就变为    sign -> 1

    digit -> ?   ----->   之后考虑状态2后就变为    digit -> 2

    dot -> ?    ------>  之后考虑状态3后就变为     dot -> 3

    eE -> -1

    因为上面有问号存在,所以我们要创建新的状态让问号有归处,直至所有的状态都有归处了就完成了。所以我们先给sign->?这个问号一个状态1,那么状态1就是指它是从+-号过来的所以有:

    状态1:(之前是正负符号)

    invalid -> -1 // 无效字符肯定就是-1

    space -> -1 // 正负号接空格肯定也不符合了,果断-1

    sign -> -1 // 符号后不能有符号,-1

    digit -> ? // 正负号加一个数字是可以继续转移的

    dot -> ? // 正负号加点也是可以继续转移的

    eE -> -1 // 正负号直接加指数eE是非法的,-1

    到此,虽然状态1也还有问号,但是我们在状态0中的sign的问号就可以用红色部分代替了。

    同理,现在我们要考虑状态1中digit->?的问号,给它一个状态2,那么状态2就是指之前是一个普通数字转过来的,普通是指之前没有点,没有eE。那么状态2可以表示为:

    状态2:(之前是普通数字)

    invalid -> -1 // 无效字符肯定就是-1

    space -> ? // 之前是数字,因为以空格结尾是合法的所以要跳转,但是我们还没有这个状态,先放着

    sign -> -1 // 数字后不能有符号,-1

    digit -> 2 // 数字之后还是数字,那么这个还是普通数字,所以转移到本身,记录为2,如果此处终止,那肯定是合法的

    dot -> ? // 数字之后是点,那么可以继续转移

    eE -> ? // 数字之后加eE要继续转移,因为可能合法。

    到此我们知道如果最后状态停留在2,那就是合法的。因为能跳到2的只有之前是合法的普通数字。并且状态0中的问号也可以更新了,见状态0中紫色部分的更新

    我们根据一个状态一个状态完成问号的顺序来进行,那么接下去就是给状态0的dot -> 3,那么状态3是

    状态3:(之前是点跳过来的)

    invalid -> -1 // 无效字符肯定就是-1

    space -> -1 // 点之后空格则无效

    sign -> -1 // 点之后符号也无效

    digit -> ? // 点之后数字,那么要跳转

    dot -> -1 // 点之后点无效

    eE -> -1 // 只有一个点之后指数无效,如果是数字加点再加指数才有效,但这里只有点所以无效。

    现在,状态0就大功告成啦。

    状态0:

    invalid -> -1

    space -> 0

    sign -> 1

    digit -> 2

    dot -> 3

    eE -> -1

    亲,到这里,你应该会类推从状态1的问号开始解决了吧。拿张纸出来画一画。

    上传一张我画的:

    中间在状态2的时候跳转错了一个,调试代码之后才改的,所以你的状态可能会和我的不一样,但是只要能AC就对了。打勾的说明如果在那个状态结束那么就是合法的数字。否则就非法。

    代码如下:

    class Solution {
    public:
    bool isNumber(const char*s)
    {
        enum InputType
        {
            invalid, space, sign, digit, dot, eE, len
        };
        int trans[][len] =
        {
            -1, 0, 1, 2, 3,-1,
            -1,-1,-1, 2, 3,-1,
            -1, 4,-1, 2, 6, 5,
            -1,-1,-1, 6,-1,-1,
            -1, 4,-1,-1,-1,-1,
            -1,-1, 7, 8,-1,-1,
            -1, 4,-1, 6,-1, 5,
            -1,-1,-1, 8,-1,-1,
            -1, 4,-1, 8,-1,-1,
        };
        int state = 0;
        while(*s!='')
        {
            InputType inputType = invalid;
            if(*s == ' ')
                inputType = space;
            else if(*s == '+' || *s == '-')
                inputType = sign;
            else if(isdigit(*s))
                inputType = digit;
            else if(*s == '.')
                inputType = dot;
            else if(*s == 'e' || *s == 'E')
                inputType = eE;
            state = trans[state][inputType];
            if (state == -1)
                return false;
            s++;
        }
        return state==2 || state==4 || state==6 || state==8;
    }
    };

     写完之后还找了另一种方法,是正则表达式的,有兴趣的可以去看看

  • 相关阅读:
    软件错误,软件缺陷,软件故障与软件失效
    QEMU命令创建KVM Guest(bridge桥接)
    Linux下设置网卡随系统启动
    RHEL查看CPU等机器信息
    QEMU/KVM功能测试
    CentOS 删除自带的OpenJDK 和 安装SunJDK
    将Centos的yum源更换为国内的阿里云源
    Centos6.8下安装oracle_11gr2版主要过程
    Centos6.8下安装oracle_11gr2版主要过程
    opendrive.com提供的免费网盘
  • 原文地址:https://www.cnblogs.com/higerzhang/p/4086191.html
Copyright © 2020-2023  润新知