请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。
思路:有限状态自动机的应用,参考:官方题解。
class Solution {
enum CharType {
CHAR_NUMBER,
CHAR_EXP,
CHAR_POINT,
CHAR_SIGN,
CHAR_SPACE,
CHAR_ILLEGAL,
}
enum State {
STATE_INITIAL,
STATE_INT_SIGN,
STATE_INTEGER,
STATE_POINT,
STATE_POINT_WITHOUT_INT,
STATE_FRACTION,
STATE_EXP,
STATE_EXP_SIGN,
STATE_EXP_NUMBER,
STATE_END,
}
public boolean isNumber(String s) {
Map<State, Map<CharType, State>> transfer = new HashMap<>();
Map<CharType, State> initialMap = new HashMap<>() {
{
put(CharType.CHAR_SPACE, State.STATE_INITIAL);
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
put(CharType.CHAR_SIGN, State.STATE_INT_SIGN);
}
};
transfer.put(State.STATE_INITIAL, initialMap);
Map<CharType, State> intSignMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_POINT, State.STATE_POINT_WITHOUT_INT);
}
};
transfer.put(State.STATE_INT_SIGN, intSignMap);
Map<CharType, State> integerMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_INTEGER);
put(CharType.CHAR_EXP, State.STATE_EXP);
put(CharType.CHAR_POINT, State.STATE_POINT);
put(CharType.CHAR_SPACE, State.STATE_END);
}
};
transfer.put(State.STATE_INTEGER, integerMap);
Map<CharType, State> pointMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
put(CharType.CHAR_EXP, State.STATE_EXP);
put(CharType.CHAR_SPACE, State.STATE_END);
}
};
transfer.put(State.STATE_POINT, pointMap);
Map<CharType, State> pointWithoutIntMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_FRACTION);
}
};
transfer.put(State.STATE_POINT_WITHOUT_INT, pointWithoutIntMap);
Map<CharType,State> fractionMap=new HashMap<>(){
{
put(CharType.CHAR_NUMBER,State.STATE_FRACTION);
put(CharType.CHAR_EXP,State.STATE_EXP);
put(CharType.CHAR_SPACE,State.STATE_END);
}
};
transfer.put(State.STATE_FRACTION,fractionMap);
Map<CharType, State> expMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
put(CharType.CHAR_SIGN, State.STATE_EXP_SIGN);
}
};
transfer.put(State.STATE_EXP,expMap);
Map<CharType,State> expSignMap=new HashMap<>(){
{
put(CharType.CHAR_NUMBER,State.STATE_EXP_NUMBER);
}
};
transfer.put(State.STATE_EXP_SIGN,expSignMap);
Map<CharType, State> expNumberMap = new HashMap<>() {
{
put(CharType.CHAR_NUMBER, State.STATE_EXP_NUMBER);
put(CharType.CHAR_SPACE, State.STATE_END);
}
};
transfer.put(State.STATE_EXP_NUMBER, expNumberMap);
Map<CharType, State> endMap = new HashMap<>() {
{
put(CharType.CHAR_SPACE, State.STATE_END);
}
};
transfer.put(State.STATE_END, endMap);
int len = s.length();
State state = State.STATE_INITIAL;
for (int i = 0; i < len; i++) {
CharType type = toCharType(s.charAt(i));
if (!transfer.get(state).containsKey(type))
return false;
else
state = transfer.get(state).get(type);
}
return state == State.STATE_INTEGER || state == State.STATE_POINT
|| state == State.STATE_FRACTION || state == State.STATE_EXP_NUMBER
|| state == State.STATE_END;
}
private CharType toCharType(char c) {
if (c >= '0' && c <= '9') return CharType.CHAR_NUMBER;
if (c == 'e' || c == 'E') return CharType.CHAR_EXP;
if (c == '.') return CharType.CHAR_POINT;
if (c == '+' || c == '-') return CharType.CHAR_SIGN;
if (c == ' ') return CharType.CHAR_SPACE;
return CharType.CHAR_ILLEGAL;
}
}