剑指Offer_#20_表示数值的字符串
Contents
题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"、"-1E-16"及"12e+5.4"都不是。
思路分析
数字字符串遵循的模式为A[.[B]][e|EC]
或者.B[e|EC]
。
数字字符串当中有两个分界点,
- 小数点
.
- 指数符号
e
或E
两个分界点,分出了三段数字部分,
A
是小数点之前的整数部分,可以带有正负号B
是小数点之后,指数符号之前的小数部分,不可带有正负号C
是指数符号之后的整数部分,可以带有正负号
注意这其中需要特殊考虑的字符就是正负号。
算法思路
首先设置几个boolean
变量作为flag,用来记录之前是否已经遇到过字符'0'-'9'
,字符.
,字符e
或E
从前往后遍历字符串,根据当前遇到的字符以及记录下来的flag,判断是否是合法的数字字符串。
解答
class Solution {
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'){
//出现数字'0'~'9',则标记numSeen为true
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;
//e之后,必须有整数,所以需要把numSeen重置为false
numSeen = false;
}else if(str[i] == '-' || str[i] == '+'){
//正负号只能出现在0位置或者e后面的第一个位置
if(i != 0 && str[i - 1] != 'e' && str[i - 1] != 'E') return false;
}else{
//出现其他字符都是不合法的
return false;
}
}
//循环到最后一个字符,如果是遇到非法情况,循环未结束就直接返回false了
//如果循环到最后一个字符,还没有返回false,就判断numSeen是否为true即可
return numSeen;
}
}
复杂度分析
时间复杂度:O(n)
,n
为字符串的长度。