剑指offer-有限状态自动机-先定义状态、再画状态转移图、最后编写代码

解题最重要难点的是根据题意去,发掘出各个状态的定义

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

题目链接:力扣

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

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

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

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

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

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

题目状态分析:其实就是分析出最长的路径,按照数值的定义,一个个状态定义

  • 0:开始空格,想要到0状态要加空格
  • 1:幂前正负号
  • 2.数字
  • 3.点.后面的数字,要到此状态要加点数字,这里不知道为什么这两个代表一个状态,应该也可以分开。是因为题目要求至少一个么
  • 4.空格后加点、数字
  • 5.e幂符号
  • 6.幂后正负号
  • 7.幂后数字
  • 8.最后空格

画状态图:跟数电一样,再用哈希表储存可以转移的状态。

剑指offer-有限状态自动机-先定义状态、再画状态转移图、最后编写代码_第1张图片

 算法流程:

1.初始化:

        状态转移表states:设states[i],i表示状态,就是上面定义的0-8的状态。states[i]使用哈希表储存可转移至的状态。键值对(key,value)含义:若输入key,则可以从状态i转移至状态value。这里哈希表的定义很重要,是一维的Map; 

        当前状态p:起始状态初始化为p=0.

Map[] states={

    new HashMap<>(){{put(' ',0);put('s',1);put('d',2);put('.',4);}},//0
    new HashMap<>() {{ put('d', 2); put('.', 4); }},                           // 1.
    new HashMap<>() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, // 2.
    new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }},              // 3.
    new HashMap<>() {{ put('d', 3); }},                                        // 4.
    new HashMap<>() {{ put('s', 6); put('d', 7); }},                           // 5.
    new HashMap<>() {{ put('d', 7); }},                                        // 6.
    new HashMap<>() {{ put('d', 7); put(' ', 8); }},                           // 7.
    new HashMap<>() {{ put(' ', 8); }}                                         // 8    
};

2.状态转移循环:遍历字符串s的每个字符c。

        记录字符类型t:分为四种情况。

  •   当c为正负号时,执行t='s';
  • 当c为数字时,执行t='d';
  • 当c为e,E时,执行t='e';
  • 当c为.,空格时,执行t=c(即用字符本身表示字符类型);
  • 否则,执行t='?',表示为不属于判断范围的非法字符,后续直接返回false。

终止条件: 若字符类型t不在哈希表states[p]中,说明无法转移至下一状态,因此直接返回False.

//这里判断p是对应的map数组第p个,检查t是否再states[p]的map数组
if(!states[p].containsKey(t)) return false;
p = (int)states[p].get(t)

状态转移:状态p转移至states[p][t];

3.返回值:跳出循环后,状态p=2/3/7/8,说明结尾合法,返回True,否则返回false;

class Solution {
    public boolean isNumber(String s) {
        //1.定义状态表s表示正负号,d表示数字,e表示幂数
        Map[] states = {
            new HashMap<>() {{put(' ',0);put('d',2);put('s',1);put('.',4);}},//0
            new HashMap<>() {{put('d',2);put('.',4);}},//1
            new HashMap<>() {{put('d',2);put('.',3);put(' ',8);put('e',5);}},//2
            new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }},              // 3.
            new HashMap<>() {{ put('d', 3); }},                                        // 4.
            new HashMap<>() {{ put('s', 6); put('d', 7); }},                           // 5.
            new HashMap<>() {{ put('d', 7); }},                                        // 6.
            new HashMap<>() {{ put('d', 7); put(' ', 8); }},                           // 7.
            new HashMap<>() {{ put(' ', 8); }}                                         // 8.
        };
        int p=0;
        //2.遍历整个字符
        char t;//这里命名可以为空
        for(char c : s.toCharArray()){
            if(c>='0' && c<='9')  t ='d';//char可以直接判断字符的大小,也算是范围
            else if(c=='e' || c=='E')  t ='e';
            else if(c==' ' || c=='.') t =c;
            else if(c=='+' || c=='-')  t ='s';
            else return false;

            if(!states[p].containsKey(t)) return false;
            p = (int)states[p].get(t);
        }
        //3.终止状态
        return (p==2 || p==3 ||p==7 ||p==8);
    }
}

你可能感兴趣的:(剑指Offer,p2p,蓝桥杯,网络协议,java)