• 剑指 Offer 20. 表示数值的字符串


    思路

    方法一:常规解法

    只检查每个字符后面的字符,需要判断的地方有:
            1. 消去字符串的前置空格和后置空格,比如“1 ”是合法的
            2. 正负号:
                (1) 只能出现在第1个字符,或者出现在e或E的后1个字符;
                (2) 正负号的后面一个字符必须是数字, 或者小数点
                (3) 最多只有2个正负号
            3. 指数e和E:
                (1) 只能出现1次 
                (2) 前面那个字符必须是数字或者小数点,如果是小数点则此小数点不能在开头位置。
                    比如.e3就是非法的,"46.e3"是合法的
                (3) 后面那个字符必须是数字或者正负号
                (4) 后面的所有字符都不能出现小数点,这一点可以在小数点的第(3)个判断点再进行判断
            4. 小数点:
                (1) 只能出现1次 
                (2) 不能出现在e或E后面的任何位置
                (3) 出现在结尾,前面那个字符必须是数字。比如123.是合法的
            5. 前置0:可以存在任意个前置0
     
      1 class Solution {
      2 private:
      3     int ePos = -1;              //E或e的位置(下标)
      4     int plusMinusSignNum = 0;   //正负号的个数
      5     int pointPos = -1;          //小数点的位置
      6 
      7 public:
      8     bool isNumber(string s) {
      9 
     10         /*1. 消去字符串前置空格和后置空格*/
     11         if(s.empty())
     12             return false;
     13 
     14         int start = 0, end = s.length()-1;
     15         for(int i = 0; i < s.length(); ++i) {
     16             if(s[i] == ' ')
     17                 start++;
     18             else
     19                 break;
     20         }
     21 
     22         if(start == s.length())
     23             return false;
     24 
     25         for(int i = s.length()-1; i >= 0; --i) {
     26             if(s[i] == ' ')
     27                 end--;
     28             else
     29                 break;
     30         }
     31 
     32         string s2(end-start+1, ' ');
     33         copy(s.begin()+start, s.begin()+end+1, s2.begin());
     34         s = string(s2.begin(), s2.end());
     35 
     36         for(int i = 0; i < s.length(); ++i) {
     37             if(s[i] == '+' || s[i] == '-') {
     38                 /*2. 检查正负号*/
     39                 //(1)只能出现在第1个字符,或者出现在e或E的后1个字符;
     40                 if(i != ePos+1) 
     41                     return false;
     42                 //(2)正负号的后面一个字符必须是数字, 或者小数点
     43                 if(i+1 <= s.length()-1) {
     44                     if(!( (s[i+1] >= '0' && s[i+1] <= '9') || s[i+1] == '.' ))
     45                         return false;
     46                 } else {
     47                     //后面无字符,直接返回false
     48                     return false;
     49                 }
     50                 
     51                 plusMinusSignNum++;
     52                 //(3)最多只有2个正负号
     53                 if(plusMinusSignNum > 2)
     54                     return false;
     55 
     56             } else if(s[i] == 'e' || s[i] == 'E') {
     57                 /*3. 检查E或e*/
     58                 //(1)只能出现1次 
     59                 if(ePos != -1)
     60                     return false;
     61                   
     62                 ePos = i;
     63 
     64                 if(i-1 >= 0) {
     65                     //(2)前面那个字符必须是数字或者小数点,如果是小数点则此小数点不能在开头位置
     66                     if(!( ( s[i-1] >= '0' && s[i-1] <= '9') || (s[i-1] == '.' && i-1 != 0)) )
     67                         return false;
     68                 } else {
     69                     //前面无字符,直接返回false
     70                     return false;
     71                 }
     72                 
     73                 //(3)后面那个字符必须是数字或者正负号
     74                 if(i+1 <= s.length()-1) {
     75                     if(!( (s[i+1] >= '0' && s[i+1] <= '9') || s[i+1] == '+' || s[i+1] == '-' ))
     76                         return false;
     77                 } else {
     78                     //后面无字符,直接返回false
     79                     return false;
     80                 }
     81 
     82             } else if(s[i] == '.') {
     83                 /*4. 检查小数点*/
     84 
     85                 //(1)只能出现1次
     86                 if(pointPos != -1)
     87                     return false;
     88 
     89                 pointPos = i;
     90 
     91                 //(2)不能出现在e或E后面的任何位置
     92                 if(pointPos > ePos && ePos != -1)
     93                     return false;
     94 
     95                 //(3)出现在结尾,前面那个字符必须是数字
     96                 if(i == s.length()-1) {
     97                     if(i-1 >= 0) {
     98                         if(s[i-1] < '0' || s[i-1] > '9')
     99                             return false;
    100                     } else {
    101                         return false;
    102                     }
    103 
    104                 } 
    105                 
    106             } else {
    107                 //其他符号中,如果有非数字符号
    108                 if(s[i] < '0' || s[i] > '9')
    109                     return false;
    110             }
    111         }
    112 
    113         return true;
    114 
    115     }
    116 };

    方法二:有限状态自动机

    本解法来自:面试题20. 表示数值的字符串(有限状态自动机,清晰图解)

    C++实现

     1 class Solution {
     2 private:
     3     /*有限状态自动机DFA*/
     4     unordered_map<char, int> states[9] = {
     5         unordered_map<char, int>({{' ', 0}, {'s', 1}, {'d', 2}, {'.', 4}}),        // 0.
     6         unordered_map<char, int>({{'d', 2}, {'.', 4}}),                            // 1.
     7         unordered_map<char, int>({{'d', 2}, {'.', 3}, {'e', 5}, {' ', 8}}),        // 2.
     8         unordered_map<char, int>({{'d', 3}, {'e', 5}, {' ', 8}}),                  // 3.
     9         unordered_map<char, int>({{'d', 3}}),                                      // 4.
    10         unordered_map<char, int>({{'s', 6}, {'d', 7}}),                            // 5.
    11         unordered_map<char, int>({{'d', 7}}),                                      // 6.
    12         unordered_map<char, int>({{'d', 7}, {' ', 8}}),                            // 7.
    13         unordered_map<char, int>({{' ', 8}})                                       // 8.
    14     };
    15         
    16 public:
    17     bool isNumber(string s) {
    18         int p = 0;
    19         char t;
    20         for(char c : s) {
    21             if(c >= '0' && c <= '9') t = 'd';
    22             else if(c == '+' || c == '-') t = 's';
    23             else if(c == 'e' || c == 'E') t = 'e';
    24             else if(c == '.' || c == ' ') t = c;
    25             else t = '?';
    26             if(states[p].count(t) == 0) 
    27                 return false;
    28             p = (int)states[p][t];
    29         }
    30         return p == 2 || p == 3 || p == 7 || p == 8;
    31     }
    32 };

    Java实现

     1 class Solution {
     2     public boolean isNumber(String s) {
     3         Map[] states = {
     4             new HashMap<>() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, // 0.
     5             new HashMap<>() {{ put('d', 2); put('.', 4); }},                           // 1.
     6             new HashMap<>() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, // 2.
     7             new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }},              // 3.
     8             new HashMap<>() {{ put('d', 3); }},                                        // 4.
     9             new HashMap<>() {{ put('s', 6); put('d', 7); }},                           // 5.
    10             new HashMap<>() {{ put('d', 7); }},                                        // 6.
    11             new HashMap<>() {{ put('d', 7); put(' ', 8); }},                           // 7.
    12             new HashMap<>() {{ put(' ', 8); }}                                         // 8.
    13         };
    14         int p = 0;
    15         char t;
    16         for(char c : s.toCharArray()) {
    17             if(c >= '0' && c <= '9') t = 'd';
    18             else if(c == '+' || c == '-') t = 's';
    19             else if(c == 'e' || c == 'E') t = 'e';
    20             else if(c == '.' || c == ' ') t = c;
    21             else t = '?';
    22             if(!states[p].containsKey(t)) return false;
    23             p = (int)states[p].get(t);
    24         }
    25         return p == 2 || p == 3 || p == 7 || p == 8;
    26     }
    27 }
  • 相关阅读:
    php函数名后冒号(:)+数据类型(返回值类型限制/php新特性)
    qBittorrent 任务数
    TDDFT软件 octopus 编译
    visual studio code, latex workshop, setting.json
    Tex插入图片/插入tikz流程图
    记录一下讨厌的东西,就当黑名单了
    安装mingw-w64
    win7 和 win10窗口的小区别
    lattice, reciprocal lattice, OUTCAR
    v_sim 个人用户编译 无root权限
  • 原文地址:https://www.cnblogs.com/FengZeng666/p/13863856.html
Copyright © 2020-2023  润新知