[LeetCode 65] Valid Number

题目

Validate if a given string can be interpreted as a decimal number.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true
" -90e3 " => true
" 1e" => false
"e3" => false
" 6e-1" => true
" 99e2.5 " => false
"53.5e93" => true
" --6 " => false
"-+3" => false
"95a54e53" => false

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:

  • Numbers 0-9
  • Exponent - “e”
  • Positive/negative sign - “+”/"-"
  • Decimal point - “.”

Of course, the context of these characters also matters in the input.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button to reset your code definition.

思路

  1. 条件判断很多,如果采用if else需要写非常多的判断分支;并且每遍历一个字符都需要基于前面遍历过的信息来判断,可以将前面遍历的信息映射为一个状态(比如,是否为整数、double、带符号数等),每遍历一个字符都根据前一个状态来判断是否合法,并且可以得到新的状态。即通过状态机来简化判断逻辑;
  2. 状态机的三个要素:状态定义,输入条件,状态转移矩阵;需要定义的状态举例:(空字符开头)起始状态,整数状态、double数状态、科学计数状态等;输入条件:空字符、正负符号、数字、E/e、非法字符;状态转移矩阵为判断核心。基于前一状态,根据输入条件来判断当前状态是否成立,因为状态和输入条件都是有限的,所以矩阵可以提前计算好,以二维数组存放即可。这也算用空间换取判断逻辑的时间。

Code in C++

class Solution {
public:
    bool isNumber(string s) {
       
        int state[10][5] = {{0, 1, 2, -1, 4},             // begin or blank
                         {-1, -1, 2, -1, 4},           // sign before exponent
                         {-1, -1, -1, -1, 7},          // dot, no number before it
                         {-1, 9, -1, -1, 5},            // exponent
                         {8, -1, 6, 3, 4},              // number 
                         {8, -1, -1, -1, 5},           // exponent number
                         {8, -1, -1, 3, 7},            // dot with number front
                         {8, -1, -1, 3, 7},            // number with dot front
                         {8, -1, -1, -1, -1},                 // blank at end
                         {-1, -1, -1, -1, 5}          // sign after exponet
                        };
        
        int pre = 0, cur = 0, input;
        for (int i = 0; i < s.size(); i++) {
            pre = cur;
            if (s[i] == ' ')
                input = 0;
            else if (s[i] == '+' || s[i] == '-')
                input = 1;
            else if (s[i] == '.')
                input = 2;
            else if (s[i] == 'E' || s[i] == 'e')
                input = 3;
            else if (s[i] >= '0' && s[i] <= '9')
                input = 4;
            else
                input = -1;
            
            if (input == -1 || (cur=state[pre][input]) == -1)
                return false;   

        }
        
        return cur > 3 && cur < 9;
    }
};

性能

[LeetCode 65] Valid Number

优化方案