剑指 Offer 20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
- 若干空格
- 一个 小数 或者 整数
- (可选)一个 ‘e’ 或 ‘E’ ,后面跟着一个 整数
- 若干空格
小数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-‘)
- 下述格式之一:
- 至少一位数字,后面跟着一个点 ‘.’
- 至少一位数字,后面跟着一个点 ‘.’ ,后面再跟着至少一位数字
- 一个点 ‘.’ ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
- (可选)一个符号字符(’+’ 或 ‘-‘)
- 至少一位数字
部分数值列举如下:
["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
部分非数值列举如下:
["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
示例 1:
输入:s = "0"
输出:true
method
enum State {
STATE_INITIAL, // 起始的空格
STATE_INT_SIGN, // 符号位
STATE_INTEGER, // 整数部分
STATE_POINT, // 左侧有整数的小数点
STATE_POINT_WITHOUT_INT, // 左侧无整数的小数点
STATE_FRACTION, // 小数部分
STATE_EXP, // 字符e/E
STATE_EXP_SIGN, // 指数部分的符号位
STATE_EXP_NUMBER, // 指数部分的整数部分
STATE_END // 末尾的空格
};
enum CharType {
CHAR_NUMBER, // 数字
CHAR_EXP, // 指数e/E
CHAR_POINT, // 点
CHAR_SIGN, // 符号
CHAR_SPACE, // 空格
CHAR_ILLEGAL // 非法输入
};
CharType toCharType(char ch) {
if (ch >= '0' && ch <= '9') return CHAR_NUMBER;
else if (ch == 'e' || ch == 'E') return CHAR_EXP;
else if (ch == '.') return CHAR_POINT;
else if (ch == '+' || ch == '-') return CHAR_SIGN;
else if (ch == ' ') return CHAR_SPACE;
else return CHAR_ILLEGAL;
}
bool isNumber(string s) {
unordered_map<State, unordered_map<CharType, State>> transfer {
{
STATE_INITIAL, {
{CHAR_SPACE, STATE_INITIAL},
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_POINT, STATE_POINT_WITHOUT_INT},
{CHAR_SIGN, STATE_INT_SIGN}
}
}, {
STATE_INT_SIGN, {
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_POINT, STATE_POINT_WITHOUT_INT}
}
}, {
STATE_INTEGER, {
{CHAR_NUMBER, STATE_INTEGER},
{CHAR_EXP, STATE_EXP},
{CHAR_POINT, STATE_POINT},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_POINT, {
{CHAR_NUMBER, STATE_FRACTION},
{CHAR_EXP, STATE_EXP},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_POINT_WITHOUT_INT, {
{CHAR_NUMBER, STATE_FRACTION}
}
}, {
STATE_FRACTION, {
{CHAR_NUMBER, STATE_FRACTION},
{CHAR_EXP, STATE_EXP},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_EXP, {
{CHAR_NUMBER, STATE_EXP_NUMBER},
{CHAR_SIGN, STATE_EXP_SIGN}
}
}, {
STATE_EXP_SIGN, {
{CHAR_NUMBER, STATE_EXP_NUMBER}
}
}, {
STATE_EXP_NUMBER, {
{CHAR_NUMBER, STATE_EXP_NUMBER},
{CHAR_SPACE, STATE_END}
}
}, {
STATE_END, {
{CHAR_SPACE, STATE_END}
}
}
};
State st = STATE_INITIAL;
for (int i= 0; i < s.size(); i++) {
CharType type = toCharType(s[i]);
if (transfer[st].find(type) == transfer[st].end()) {
return false;
}
else {
st = transfer[st][type];
}
}
return st == STATE_INTEGER || st == STATE_POINT || st == STATE_FRACTION || st == STATE_EXP_NUMBER || st == STATE_END;
}