剑指 Offer 20. 表示数值的字符串
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。
思路
有限状态自动机。设计状态的时候注意由于".1"这样的字符串是合法的而"."这样的字符串是非法的,因此针对’.‘要设计两个状态: DOT, DOT_NO_DIG. 前者表示’.‘之前已有数字,后者表示’.'之前没有数字。另外注意字符串前后可能含有空格,但字符串前后的空格不影响字符串的含义(字符串中间的空格会使得字符串非法),因此要提前用strip
或trim
方法对字符串进行预处理。
代码
class Solution {
private static final short START = -1, SIGN_A = 0, DIG_A0 = 1, DOT = 2, DOT_NO_DIG = 3, DIG_A1 = 4, E = 5, SIGN_B = 6, DIG_B = 7;
private short getCharType(char ch) {
if (ch >= '0' && ch <= '9') {
return 0;
} else if (ch == '+' || ch == '-') {
return 1;
} else if (ch == '.') {
return 2;
} else if (ch == 'E' || ch == 'e') {
return 3;
} else {
return -1;
}
}
public boolean isNumber(String s) {
s = s.strip();
short state = START;
for (char ch: s.toCharArray()) {
short type = getCharType(ch);
if (type == -1) {
return false;
}
switch (state) {
case START:
switch (type) {
case 0:
state = DIG_A0;
break;
case 1:
state = SIGN_A;
break;
case 2:
state = DOT_NO_DIG;
break;
default:
return false;
}
break;
case SIGN_A:
switch (type) {
case 0:
state = DIG_A0;
break;
case 2:
state = DOT_NO_DIG;
break;
default:
return false;
}
break;
case DIG_A0:
switch (type) {
case 0:
state = DIG_A0;
break;
case 2:
state = DOT;
break;
case 3:
state = E;
break;
default:
return false;
}
break;
case DOT:
switch (type) {
case 0:
state = DIG_A1;
break;
case 3:
state = E;
break;
default:
return false;
}
break;
case DOT_NO_DIG:
switch (type) {
case 0:
state = DIG_A1;
break;
default:
return false;
}
break;
case DIG_A1:
switch (type) {
case 0:
state = DIG_A1;
break;
case 3:
state = E;
break;
default:
return false;
}
break;
case E:
switch (type) {
case 0:
state = DIG_B;
break;
case 1:
state = SIGN_B;
break;
default:
return false;
}
break;
case SIGN_B:
switch (type) {
case 0:
state = DIG_B;
break;
default:
return false;
}
break;
case DIG_B:
switch (type) {
case 0:
state = DIG_B;
break;
default:
return false;
}
break;
default:
return false;
}
}
return state != START && state != DOT_NO_DIG && state != E && state != SIGN_A && state != SIGN_B;
}
}