剑指 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
;
}
}