题目:
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.
题解:此题若考虑用各种条件判别,将十分繁琐,因为输入的组合可能太多。网上学来有限状态机做法,十分便捷(点击打开链接)
假设输入有六种类型:
0:INVALID, //各种除下面字符外的无效字符
1:SPACE, // ‘ ’
2:SIGN, // '+','-'
3:DIGIT, // 数字
4:DOT, // '.'
5:EXPONENT, // 'e' 'E'
假设有九种状态:
0:初始无输入或者只有space的状态
1:输入了数字之后的状态
2:前面无数字,只输入了Dot的状态
3:输入了符号状态
4:前面有数字和有dot的状态
5:'e' or 'E'输入后的状态
6:输入e之后输入Sign的状态
7:输入e后输入数字的状态
8:前面有有效数输入之后,输入space的状态
制作一张由输入跳转状态的有限状态表:
//INV SP SI DI DO EXP
-1, 0, 3, 1, 2, -1, //0初始无输入或者只有space的状态
-1, 8, -1, 1, 4, 5, //1输入了数字之后的状态
-1, -1, -1, 4, -1, -1, //2前面无数字,只输入了Dot的状态
-1, -1, -1, 1, 2, -1, //3输入了符号状态
-1, 8, -1, 4, -1, 5, //4前面有数字和有dot的状态
-1, -1, 6, 7, -1, -1, //5'e' or 'E'输入后的状态
-1, -1, -1, 7, -1, -1, //6输入e之后输入Sign的状态
-1, 8, -1, 7, -1, -1, //7输入e后输入数字的状态
-1, 8, -1, -1, -1, -1, //8前面有有效数输入之后,输入space的状态
其中-1表示无效状态,若值为-1,则当前输入为非数字,直接返回false。
c++版:
class Solution {
public:
bool isNumber(const char *s) {
int stateTransitTable[9][6] = {
//INVALID SPACE SIGN DIGIT DOT EXPONENT
-1, 0, 3, 1, 2, -1, //0初始无输入或者只有space的状态
-1, 8, -1, 1, 4, 5, //1输入了数字之后的状态
-1, -1, -1, 4, -1, -1, //2前面无数字,只输入了Dot的状态
-1, -1, -1, 1, 2, -1, //3输入了符号状态
-1, 8, -1, 4, -1, 5, //4前面有数字和有dot的状态
-1, -1, 6, 7, -1, -1, //5'e' or 'E'输入后的状态
-1, -1, -1, 7, -1, -1, //6输入e之后输入Sign的状态
-1, 8, -1, 7, -1, -1, //7输入e后输入数字的状态
-1, 8, -1, -1, -1, -1, //8前面有有效数输入之后,输入space的状态
};
int lastState = 0;
while(*s != '\0') {
int input;
if(*s == ' ') input = 1;
else if(*s == '+' || *s == '-') input = 2;
else if(isdigit(*s)) input = 3;
else if(*s == '.') input = 4;
else if(*s == 'e' || *s == 'E') input = 5;
else input = 0;
lastState = stateTransitTable[lastState][input];
if(lastState == -1)
return false;
s++;
}
return lastState == 1 || lastState == 4 || lastState == 7 || lastState == 8;
}
};
Java版:
public class Solution {
public boolean isNumber(String s) {
int stateTransit[][] = {
{-1, 0, 3, 1, 2, -1},
{-1, 8, -1, 1, 4, 5},
{-1, -1, -1, 4, -1, -1},
{-1, -1, -1, 1, 2, -1},
{-1, 8, -1, 4, -1, 5},
{-1, -1, 6, 7, -1, -1},
{-1, -1, -1, 7, -1, -1},
{-1, 8, -1, 7, -1, -1},
{-1, 8, -1, -1, -1, -1}
};
int state = 0;
for(int i = 0; i < s.length(); i++) {
int input;
if(s.charAt(i) == ' ') input = 1;
else if(s.charAt(i) == '+' || s.charAt(i) == '-') input = 2;
else if(Character.isDigit(s.charAt(i))) input = 3;
else if(s.charAt(i) == '.') input = 4;
else if(s.charAt(i) == 'e' || s.charAt(i) == 'E') input = 5;
else input = 0;
state = stateTransit[state][input];
if(state == -1)
return false;
}
return state == 1 || state == 4 || state == 7 || state == 8;
}
}
Python版:
class Solution:
# @param s, a string
# @return a boolean
def isNumber(self, s):
stateTrans = [[-1, 0, 3, 1, 2, -1],
[-1, 8, -1, 1, 4, 5],
[-1, -1, -1, 4, -1, -1],
[-1, -1, -1, 1, 2, -1],
[-1, 8, -1, 4, -1, 5],
[-1, -1, 6, 7, -1, -1],
[-1, -1, -1, 7, -1, -1],
[-1, 8, -1, 7, -1, -1],
[-1, 8, -1, -1, -1, -1]]
state = 0
for i in range(0, len(s)):
input = -1
if s[i] == ' ':
input = 1
elif s[i] == '+' or s[i] == '-':
input = 2
elif s[i].isdigit():
input = 3
elif s[i] == '.':
input = 4
elif s[i] == 'e' or s[i] == 'E':
input = 5
else:
input = 0
state = stateTrans[state][input]
if state == -1:
return False
return state == 1 or state == 4 or state == 7 or state == 8