题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
这道题在官方的解题思路用的是确定有限状态自动机
来实现,这个没有汇编这方面的前置知识很难想到,所以这里我就用了另外的一种方法。
首先,我们先分析一下这些正确数字和错误数字的正确原因和错误原因
123,0123,456 : 正确,纯数字
+100,-100:正确,1+123,"+ -5":错误
数字前面有加号或减号时, 加号和减号前没有数字和其他符号
“5e2”,"-1E-16":正确, “1a3.14”,“12e+5.4”,“12e”:错误
e/E是科学计数法,表示的是10的多少次方,例如5e2就是5乘以10的2次方
在上面的例子中可以知道:(1)数字中可以有字母e/E,但是其他字母不行.(2)e前e后必有数,但是必须为整数
“3.1416”,“0.67”:正确,“1.2.3”,".23","“23.”":错误
小数点可以出现在数字之间,但是只能出现一次
从上面的例子分析,我们可以了解到:
(1) 单纯的数字时正确的
(2)加减号要出现在数字前而且不能连续
(3)小数点只能出现在数字之间,而且只能出现一次
(4)数字中可以有字母e/E,但是其他字母不行
(5)e前e后必有数,但是必须为整数
根据上面得出的结论中,我们划分为3种状态,只有这4个状态都符合了就是数字字符串.
- 数字位置: 任意
- 加减号位置:只能在数字之前,必须是在第一个字符的位置,但是除了出现e的情况
- e/E的位置:e前后必须有数,带正负号都可以,但不能出现小数点
- 小数点的位置:只能出现一次,小数点前后都有数
因此我们根据上面的分析结论,对一个字符串中的字符进行遍历,对其中的字符进行判断,同时用numSeen (记录是否有了数字的情况),dotSeen (是否有了小数点的情况),eSeen (是否有了e/E的情况)同时判断数字是否成立的情况.
代码
//code
public boolean isNumber(String s) {
if(s == null || s.length() == 0){
return false;
}
//标记是否遇到相应情况
boolean numSeen = false;
boolean dotSeen = false;
boolean eSeen = false;
char[] str = s.trim().toCharArray();
for(int i = 0;i < str.length; i++){
if(str[i] >= '0' && str[i] <= '9'){
numSeen = true;
}else if(str[i] == '.'){
//.之前不能出现.或者e
if(dotSeen || eSeen){
return false;
}
dotSeen = true;
}else if(str[i] == 'e' || str[i] == 'E'){
//e之前不能出现e,必须出现数
if(eSeen || !numSeen){
return false;
}
eSeen = true;
numSeen = false;//重置numSeen,排除123e或者123e+的情况,确保e之后也出现数
}else if(str[i] == '-' || str[i] == '+'){
//+-出现在0位置或者e/E的后面第一个位置才是合法的
if(i != 0 && str[i-1] != 'e' && str[i-1] != 'E'){
return false;
}
}else{//其他不合法字符
return false;
}
}
return numSeen;
}