Old discuss is read-only now. Please go to New LeetCode Discuss for your questions and answers!

User account in old discuss will not integrate to the new one, but new discuss is integrated with new online judge, which means, if you already have an account in new online judge, you can access new discuss immediately!

If you want to ask for question relevant to the posts in old discuss, please copy content as part of your question, only old discuss link is NOT ALLOWED!

Please read the FAQ in new LeetCode Discuss to help yourself making the best use of Discuss!

0
1

Validate if a given string is numeric.

Some examples:
"0" => true
" 0.1 " => true
"abc" => false
"1 a" => false
"2e10" => true

Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.

asked 02 Apr '12, 12:37

1337c0d3r's gravatar image

1337c0d3r ♦♦
1.2k1384171
accept rate: 2%

closed 25 Oct '13, 06:41

The question has been closed for the following reason "bulk close" by 1337c0d3r 25 Oct '13, 06:41


My solution using finite automata (inspired by @luckynoob):

bool isNumber(const char *s) {
    enum InputType {
        INVALID,    // 0
        SPACE,      // 1
        SIGN,       // 2
        DIGIT,      // 3
        DOT,        // 4
        EXPONENT,   // 5
        NUM_INPUTS  // 6
    };
    int transitionTable[][NUM_INPUTS] = {
        -1,  0,  3,  1,  2, -1,     // next states for state 0
        -1,  8, -1,  1,  4,  5,     // next states for state 1
        -1, -1, -1,  4, -1, -1,     // next states for state 2
        -1, -1, -1,  1,  2, -1,     // next states for state 3
        -1,  8, -1,  4, -1,  5,     // next states for state 4
        -1, -1,  6,  7, -1, -1,     // next states for state 5
        -1, -1, -1,  7, -1, -1,     // next states for state 6
        -1,  8, -1,  7, -1, -1,     // next states for state 7
        -1,  8, -1, -1, -1, -1,     // next states for state 8
    };

int state = 0;
while (*s != '\0') {
    InputType inputType = INVALID;
    if (isspace(*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 = EXPONENT;

    // Get next state from current state and input symbol
    state = transitionTable[state][inputType];

    // Invalid input
    if (state == -1) return false;
    else ++s;
}
// If the current state belongs to one of the accepting (final) states,
// then the number is valid
return state == 1 || state == 4 || state == 7 || state == 8;

}

link

answered 18 Jan '13, 08:21

Lu-An%20Gong's gravatar image

Lu-An Gong
44846
accept rate: 7%

edited 18 Jan '13, 08:47

Very nice diagram! Now I wish I had taken the class in finite automata.

(18 Jan '13, 21:53) 1337c0d3r ♦♦ 1337c0d3r's gravatar image

Much better !

(20 Jan '13, 16:02) luckynoob luckynoob's gravatar image
bool isNumber(const char *s) {
    int mat[11][7] = {0 ,0 ,0 ,0 ,0 ,0 ,0, // false
                      0 ,2 ,3 ,0 ,1 ,4 ,0, // 1
                      0 ,2 ,5 ,6 ,9 ,0 ,10,// 2
                      0 ,5 ,0 ,0 ,0 ,0 ,0, // 3
                      0 ,2 ,3 ,0 ,0 ,0 ,0, // 4
                      0 ,5 ,0 ,6 ,9 ,0 ,10,// 5
                      0 ,7 ,0 ,0 ,0 ,8 ,0, // 6
                      0 ,7 ,0 ,0 ,9 ,0 ,10,// 7
                      0 ,7 ,0 ,0 ,0 ,0 ,0, // 8
                      0 ,0 ,0 ,0 ,9 ,0 ,10,// 9
                      10,10,10,10,10,10,10 // 10
                    };
    int i = 0;
    int stat = 1;
    while(s[i] != 0) {
        int type = 0;
        if(s[i] >= '0' && s[i] <= '9')
            type = 1;
        else if(s[i] == '.')
            type = 2;
        else if(s[i] == 'e')
            type = 3;
        else if(s[i] == ' ')
            type = 4;
        else if(s[i] == '+' || s[i] == '-')
            type = 5;
        if(stat == 0)
            return false;
        stat = mat[stat][type];
        i++;
    }
    stat = mat[stat][6];
    if(stat == 10)
        return true;
    else
        return false;
}
link

answered 31 Dec '12, 18:50

luckynoob's gravatar image

luckynoob
54746
accept rate: 0%

Your code looks quite elegant, but it's a little bit difficult to understand. Could you give some explanation about your transition table, or could you post your transition graph here?

(18 Jan '13, 01:31) Lu-An Gong Lu-An%20Gong's gravatar image

Well, if we are allowed to use regex, this can be done in one line code. The running time depends on how the compile parses regex though.

public boolean isNumber(String s) {
  return s.matches("^\\s*[+-]?(\\d+|\\d*\\.\\d+|\\d+\\.\\d*)([eE][+-]?\\d+)?\\s*$");
}
link

answered 27 Jun '13, 14:02

n00tc0d3r's gravatar image

n00tc0d3r
32625
accept rate: 0%

public boolean isNumber(String s) {
   if(s==null)
        return false;
    char[] sArr = s.trim().toCharArray();

    if(sArr.length==0)
        return false;
    if(sArr.length==1&&!Character.isDigit(sArr[0]))
        return false;

    boolean decimalFound = false;
    boolean eFound = false;
    int end = sArr.length-1;
    for(int i=0;i<=end;i++){        
        char nextChar = i>=end?'x':sArr[i+1];
        char prevChar = i<=0?'x':sArr[i-1];
        switch(sArr[i]){
        case '+':
        case '-':
            if(prevChar!='e'&&i!=0)
                return false;
            if(prevChar=='e'&&i==end)
                return false;
            if (i==0&&nextChar=='e')
                return false;
            break;
        case '.':
            if(decimalFound || eFound)
                return false;
            if(i>=end && i<=0)
                return false;
            if(!Character.isDigit(prevChar) && !Character.isDigit(nextChar))
                return false;
            decimalFound = true;
            break;
        case 'e':
            if(eFound)
                return false;
            if(!Character.isDigit(prevChar) && !Character.isDigit(nextChar)
                &&nextChar!='-'|| end==i || i==0){
                        return false;                        
            }
            eFound = true;
            break;
        case ' ':
            return false;
        default:
            if(!Character.isDigit(sArr[i]))
                return false;
        }

    }
    return true;
}
link

answered 09 May '13, 12:18

Tanu's gravatar image

Tanu
212
accept rate: 0%

private:

enum Token { Null, Sign, Num, Point, E, Space };
bool isDigit(char c) { return c >= '0' && c <= '9'; }
bool isSpace(char c) { return c == ' ' || c == '\t'; }

public:

bool isNumber(const char *s) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    int i = 0;
    bool hasNum = false;
    int pointCnt = 0, eCnt = 0;
    Token preToken = Token::Null;
    while (s[i] != 0) {
        if (isDigit(s[i])) hasNum = true;

        switch (preToken) {
        case Token::Null:
            if (isSpace(s[i])) break;
            else if (s[i] == '-' || s[i] == '+') { preToken = Token::Sign; break; }
            else if (s[i] == '.') { preToken = Token::Point; pointCnt++; break; }
            else if (isDigit(s[i])){ preToken = Token::Num; break;}
            else return false;

        case Token::Sign:
            if (s[i] == '.') { preToken = Token::Point; pointCnt++; break; }
            if (isDigit(s[i])){ preToken = Token::Num; break; }
            else return false;

        case Token::Num:
            if (isDigit(s[i])) break;
            else if (s[i] == 'e' || s[i] == 'E') { preToken = Token::E; eCnt++; break; }
            else if (s[i] == '.') { if (eCnt > 0) return false; preToken = Token::Point; pointCnt++; break; }
            else if (isSpace(s[i])) { preToken = Token::Space; break; }
            else return false;

        case Token::Point:
            if (isDigit(s[i])) { preToken = Token::Num; break; }
            else if (s[i] == 'e' || s[i] == 'E' || isSpace(s[i])) {
                if (!hasNum) return false;
                if (isSpace(s[i])) { preToken = Token::Space; break; }
                else { preToken = Token::E; break; }
            }
            else return false;

        case Token::E:
            if (isDigit(s[i])) { preToken = Token::Num; break; }
            else if (s[i] == '-' || s[i] == '+') { preToken = Token::Sign; break; }
            else return false;

        case Token::Space:
            if (isSpace(s[i])) break;
            else return false;
        }
        i++;
    }
    if (pointCnt > 1 || eCnt > 1)
        return false;
    if (preToken == Token::Num || preToken == Token::Space ||
        (preToken == Token::Point && hasNum))
        return true;
    return false;
}
link

answered 16 May '13, 02:00

sherryweihao's gravatar image

sherryweihao
214
accept rate: 0%

enum input_type{
    e_digit, //1
    e_point, //2
    e_exponent, //3
    e_sign, //4
    e_space, //5
    e_invalid, //6
    ENUM_SIZE //
};

input_type get_value(char s){
    switch (s) {
        case ' ': return e_space;
        case '.': return e_point;
        case 'e': return e_exponent;
        case '-': return e_sign;
        case '+': return e_sign;
        default:{
            if(s>='0' && s<='9')
                return e_digit;
            else
                return e_invalid;
        }
    }
}

bool isNumber(const char *s) {
    // Start typing your C/C++ solution below
    // DO NOT write int main() function
    int transition_table[][ENUM_SIZE] = {
         1,  6, -1,  4,  0, -1,     //state 0:begin
         1,  2,  7, -1,  5, -1,     //state 1:digit
         2, -1,  7, -1,  5, -1,     //state 2:pointed with num front
         3, -1, -1, -1,  5, -1,     //state 3:exponented with num front
         1,  6, -1, -1, -1, -1,     //state 4:signed
        -1, -1, -1, -1,  5, -1,     //state 5:space after num
         2, -1, -1, -1, -1, -1,     //state 6:pointed with out num front
         3, -1, -1,  9, -1, -1,     //state 7:exponented with out num
         8, -1, -1, -1,  5, -1,     //state 8:exponented signed
         8, -1, -1, -1, -1, -1      //state 9:exponented signed with out num after
        //stat -1:invalid
    };
    bool final_state[]={0, 1, 1, 1, 0, 1, 0, 0, 1, 0};
    int state = 0;
    while(*s != '\0' && state != -1){
        input_type in = get_value(*(s++));
        state = transition_table[state][in];
    }
    if(state == -1 || !final_state[state])
        return false;
    else
        return true;
}

more readable finite automata

link

answered 22 Jul '13, 09:33

snakeling's gravatar image

snakeling
11
accept rate: 0%

edited 22 Jul '13, 09:37

class Solution { public: bool isNumKernel(string&& s, bool num, bool point) { if (s.size()==1) { if(isdigit(s[0]) || (s[0]=='.' && num && !point)) return true; else return false; }

    if (isdigit(s[0])) return isNumKernel(s.substr(1), true, point);
    else if (s[0]=='.' && !point)   return isNumKernel(s.substr(1), num, true);
    else return false;
}

bool isNumber(const char *s) {
    // Note: The Solution object is instantiated only once and is reused by each test case.
    stringstream numCan(s);
    string first, second;
    numCan >> first >> second;
    if (first.empty() || !second.empty())  return false;

    int len = first.size();

    size_t epos = first.find('e');
    if (epos == first.size()-1)     return false;
    else if (epos <= first.size()-2)
    {
        string tmp = first.substr(epos+1);
        int len = tmp.size();
        if (len==1 && !isdigit(tmp[0]))     return false;
        if (!isdigit(tmp[0]) && (tmp[0]!='+' && tmp[0]!='-'))
            return false;
        for (int i=1; i<len; ++i)
            if (!isdigit(tmp[i]))
                return false;
    }

    second = first.substr(0, epos);
    len = second.size();
    if (len == 0)   return false;
    else if (len==1) return isdigit(second[0])?true:false;
    if (second[0]=='+' || second[0]=='-')
        return isNumKernel(second.substr(1), false, false);
    else if (second[0] == '.')
        return isNumKernel(second.substr(1), false, true);
    else if (isdigit(second[0]))
        return isNumKernel(second.substr(1), true, false);
    else 
        return false;
}

};

We can focus on the effectual string by using sstream. Dividing the string into 2 parts by 'e', the right part (if existed) should contain only sign and digits, while the left part should be a float.

link

answered 09 Oct '13, 21:12

sangoblin's gravatar image

sangoblin
111
accept rate: 0%

Ugly solution. Submitted and revised 10 time before accepted ...

public class Solution {
public boolean isNumber(String s) {
    if(s==null || s.length()==0)  return false;
    int i=0;
    int digitPointCnt = 0;
    while(i<s.length() && s.charAt(i)==' ')  i++;  // ignore prevailing spaces
    if(i<s.length() && (s.charAt(i)=='-' || s.charAt(i)=='+'))  i++;  // - or + sign
    if(i<s.length() && s.charAt(i)=='.') {
        i++;   // allow starting digit point
        digitPointCnt++;
    }
    if(isNonNum(s,i))  return false;  // start with non-num
    i = nextNonNum(s,i);  
    if(i==s.length())  return true;  // all numerics
    if(s.charAt(i)==' ')  return allSpaces(s,i);  // check trailing spaces
    if(s.charAt(i)=='.')  {
        digitPointCnt++;
        if(digitPointCnt>1)  return false;   // two digit points are invalid
        i++;
        if(i==s.length())  return true;   // allow trailing digit point
        if(s.charAt(i)==' ')  return allSpaces(s,i);
        if(s.charAt(i)=='e'||s.charAt(i)=='E')  return validExp(s,i+1);  // allow .e
        if(isNonNum(s,i))  return false;  // digit point followed by non-num
        i = nextNonNum(s,i); 
        if(i==s.length())  return true;  // all nums
        if(s.charAt(i)==' ')  return allSpaces(s,i);  // check trailing spaces
        if(s.charAt(i)=='e'||s.charAt(i)=='E')  return validExp(s,i+1);
        return false;  // any other characters are invalid
    }
    else if(s.charAt(i)=='e'||s.charAt(i)=='E')  {
        return validExp(s,i+1);
    }
    return false;
}
public boolean isNonNum(String s, int i)  {
    if(i>=s.length())  return true;
    return s.charAt(i)<'0' || s.charAt(i)>'9';
}
// find next non-num position
public int nextNonNum(String s, int i)  {
    while(i<s.length() && s.charAt(i)>='0' && s.charAt(i)<='9')  i++;
    return i;
}
// check trailing spaces
public boolean allSpaces(String s, int i)  {
    while(i<s.length() && s.charAt(i)==' ')  i++;
    if(i==s.length())  return true; 
    return false;        
}
// check valid exponential num
public boolean validExp(String s, int i)  {
    if(i<s.length() && (s.charAt(i)=='-' || s.charAt(i)=='+'))  i++;
    if(isNonNum(s,i))  return false;
    i = nextNonNum(s,i);
    if(i==s.length())  return true;  // all numerics
    if(s.charAt(i)==' ')  return allSpaces(s,i);  // check trailing spaces
    return false;
}

}

link

answered 20 Oct '13, 20:04

swang511's gravatar image

swang511
113
accept rate: 0%

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Markdown Basics

  • *italic* or _italic_
  • **bold** or __bold__
  • Indent code by 4 spaces.
  • link:[text](http://url.com/ "Title")
  • image?![alt text](/path/img.jpg "Title")
  • numbered list: 1. Foo 2. Bar
  • to add a line break simply add two spaces to where you would like the new line to be.
  • basic HTML tags are also supported

Tags:

×133

Asked: 02 Apr '12, 12:37

Seen: 4,180 times

Last updated: 25 Oct '13, 06:41