https://leetcode.com/problems/valid-number/
https://leetcode.com/problems/valid-number/discuss/23942/AC-Java-solution-with-clear-explanation
Validate if a given string can be interpreted as a decimal number.
Some examples:
"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
" -90e3 "
=> true
" 1e"
=> false
"e3"
=> false
" 6e-1"
=> true
" 99e2.5 "
=> false
"53.5e93"
=> true
" --6 "
=> false
"-+3"
=> false
"95a54e53"
=> false
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one. However, here is a list of characters that can be in a valid decimal number:
- Numbers 0-9
- Exponent - "e"
- Positive/negative sign - "+"/"-"
- Decimal point - "."
Of course, the context of these characters also matters in the input.
http://www.cnblogs.com/grandyang/p/4084408.html
我们尝试着来优化一下,根据上面的分析,所有的字符可以分为六大类,空格,符号,数字,小数点,自然底数和其他字符,我们需要五个标志变量,num, dot, exp, sign分别表示数字,小数点,自然底数和符号是否出现,numAfterE表示自然底数后面是否有数字,那么我们分别来看各种情况:
- 空格: 我们需要排除的情况是,当前位置是空格而后面一位不为空格,但是之前有数字,小数点,自然底数或者符号出现时返回false。
- 符号:符号前面如果有字符的话必须是空格或者是自然底数,标记sign为true。
- 数字:标记num和numAfterE为true。
- 小数点:如果之前出现过小数点或者自然底数,返回false,否则标记dot为true。
- 自然底数:如果之前出现过自然底数或者之前从未出现过数字,返回false,否则标记exp为true,numAfterE为false。
- 其他字符:返回false。
最后返回num && numAfterE即可。
bool isNumber(string s) { bool num = false, numAfterE = true, dot = false, exp = false, sign = false; int n = s.size(); for (int i = 0; i < n; ++i) { if (s[i] == ' ') { if (i < n - 1 && s[i + 1] != ' ' && (num || dot || exp || sign)) return false; } else if (s[i] == '+' || s[i] == '-') { if (i > 0 && s[i - 1] != 'e' && s[i - 1] != ' ') return false; sign = true; } else if (s[i] >= '0' && s[i] <= '9') { num = true; numAfterE = true; } else if (s[i] == '.') { if (dot || exp) return false; dot = true; } else if (s[i] == 'e') { if (exp || !num) return false; exp = true; numAfterE = false; } else return false; } return num && numAfterE; }https://leetcode.com/problems/valid-number/discuss/23738/Clear-Java-solution-with-ifs
All we need is to have a couple of flags so we can process the string in linear time:
We start with trimming.
- If we see
[0-9]
we reset the number flags. - We can only see
.
if we didn't seee
or.
. - We can only see
e
if we didn't seee
but we did see a number. We reset numberAfterE flag. - We can only see
+
and-
in the beginning and after ane
- any other character break the validation.
At the and it is only valid if there was at least 1 number and if we did see an
e
then a number after it as well.
So basically the number should match this regular expression:
[-+]?(([0-9]+(.[0-9]*)?)|.[0-9]+)(e[-+]?[0-9]+)?
public boolean isNumber(String s) {
s = s.trim();
boolean pointSeen = false;
boolean eSeen = false;
boolean numberSeen = false;
boolean numberAfterE = true;
for(int i=0; i<s.length(); i++) {
if('0' <= s.charAt(i) && s.charAt(i) <= '9') {
numberSeen = true;
numberAfterE = true;
} else if(s.charAt(i) == '.') {
if(eSeen || pointSeen) {
return false;
}
pointSeen = true;
} else if(s.charAt(i) == 'e') {
if(eSeen || !numberSeen) {
return false;
}
numberAfterE = false;
eSeen = true;
} else if(s.charAt(i) == '-' || s.charAt(i) == '+') {
if(i != 0 && s.charAt(i-1) != 'e') {
return false;
}
} else {
return false;
}
}
return numberSeen && numberAfterE;
}
https://leetcode.com/problems/valid-number/discuss/23942/AC-Java-solution-with-clear-explanation
public boolean isNumber(String s) {
if (s == null) return false;
s = s.trim();
int n = s.length();
if (n == 0) return false;
// flags
int signCount = 0;
boolean hasE = false;
boolean hasNum = false;
boolean hasPoint = false;
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
// invalid character
if (!isValid(c)) return false;
// digit is always fine
if (c >= '0' && c <= '9') hasNum = true;
// e or E
if (c == 'e' || c == 'E') {
// e cannot appear twice and digits must be in front of it
if (hasE || !hasNum) return false;
// e cannot be the last one
if (i == n - 1) return false;
hasE = true;
}
// decimal place
if (c == '.') {
// . cannot appear twice and it cannot appear after e
if (hasPoint || hasE) return false;
// if . is the last one, digits must be in front of it, e.g. "7."
if (i == n - 1 && !hasNum) return false;
hasPoint = true;
}
// signs
if (c == '+' || c == '-') {
// no more than 2 signs
if (signCount == 2) return false;
// sign cannot be the last one
if (i == n - 1) return false;
// sign can appear in the middle only when e appears in front
if (i > 0 && !hasE) return false;
signCount++;
}
}
return true;
}
boolean isValid(char c) {
return c == '.' || c == '+' || c == '-' || c == 'e' || c == 'E' || c >= '0' && c <= '9';
}