【LeetCode-字符串】表示数值的字符串
题目描述
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"、"-1E-16"及"12e+5.4"都不是。
题目链接: https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/
思路
表示数值的字符串的模式为A[.[B]][e|EC]
或者.B[e|EC]
,其中,A 为数值的整数部分,B 为小数部分,C 为指数部分。在小数里可能没有小数的整数部分,例如 0.123
也可以写成 .123
,所以 A 不是必须的,字符串中只能出现一个小数点,且 C 为整数。
我们设置 3 个变量:numSeen 表示是否已经找到数字、dotSeen 表示是否已经找到点、eSeen 表示是否看到 e 或者 E,这 3 个变量均初始化为 false。
算法步骤如下:
- 遍历字符串:
- 如果当前字符为数字,则设置 numSeen 为 true;
- 否则,如果当前字符为
.
,因为只能有一个点,所以点之前不能出现点,而且点不能出现在指数部分,所以我们要对 dotSeen 和 eSeen 进行判断,如果 dotSeen==true 或者 eSeen==true,则返回 false;否则设置 dotSeen 为 true; - 否则,如果当前字符为
e
或者E
,因为一个字符串中只能有一个e
或者E
且指数前要有数字,所以,我们判断 eSeen 和 numSeen 的情况。如果 eSeen==true 或者 numSeen==false,则返回 false;否则设置 eSeen 为 true 并设置 numSeen 为 false。设置 numSeen 为 false 的原因是防止出现123e
或者123e+
的情况; - 否则,如果当前字符为符号
-
或者+
,因为符号只能在字符串头出现或者在e
或者E
之后出现,所以我们判断当前位置是否是 0,如果不是,接着判断当前字符的前一个字符是不是e
或者E
,如果也不是,则返回 false。 - 否则,对于其他情况,一律返回 false;
- 最后,返回 numSeen 的情况。
代码如下:
class Solution {
public:
bool isNumber(string s) {
if(s.empty()) return false;
while(!s.empty() && s.back()==' ') s.pop_back();
int i = 0;
while(s[i]==' ') i++;
s = s.substr(i, s.size());
if(s.empty()) return false;
bool numSeen = false;
bool dotSeen = false;
bool eSeen = false;
for(int i=0; i<s.size(); i++){
if(isdigit(s[i])){
numSeen = true;
}else if(s[i]=='.'){
if(dotSeen || eSeen) return false; // 之前出现过点或者出现过e|E
else dotSeen = true;
}else if(s[i]=='e' || s[i]=='E'){
if(eSeen || !numSeen) return false;
eSeen = true;
numSeen = false; // 别忘了置为false,排除123e或者123e+的情况,确保e|E后面也是数字
}else if(s[i]=='-' || s[i]=='+'){
//+|-出现在0位置或者e|E的后面第一个位置才是合法的
if(i!=0 && s[i-1]!='e' && s[i-1]!='E') return false;
}else return false;
}
return numSeen;
}
};
- 时间复杂度:O(n)
- 空间复杂度:O(1)