065
difficulty: Hard
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.
Update (2015-02-10):
The signature of the C++
function had been updated. If you still see your function signature accepts a const char *
argument, please click the reload button to reset your code definition.
Method One
class Solution {
public boolean isNumber(String s) {
//这个问题需要讨论的是四个符号如何合法。
// e 和. 都只能出现一次。
// e 的合法是需要 e 前后都有合法数字。
// 并且 e 之前可以出现小数点,e之后只能是纯数字和首位正负号
// . 的合法是,只能出现在e之前,并且小数点前或者后面至少有数字
// + - 的合法是只能出现在字符最开始和 e 之后, 因此我们需要index的信息
// 这个字符串被e分成了两部分,当e出现之后进行第二次检查。
s = s.trim();
boolean decimalSeen = false;
boolean eSeen = false;
boolean numberSeen = false;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if( c <= '9' && c >= '0'){
numberSeen = true;
}else if( c == 'e') {
if(!numberSeen || eSeen) {
return false;
}
eSeen = true;
numberSeen = false;
}else if ( c == '.'){
if(eSeen || decimalSeen){
return false;
}
decimalSeen = true;
}else if( c == '+' || c == '-'){
// !(i == 0 || s.charAt(i - 1 ) != 'e')
}else if( c == '+' || c == '-'){
if( i != 0 && s.charAt(i - 1) != 'e'){
return false;
}
}else {
return false;
}
}
return numberSeen;
}
}
上面的代码写的有点不太易懂,我们需要把算法搞清楚,下面的可读性会强一点。
class Solution {
// 学英语 一个小数 decimal number
// 整数部分 integer part, 小数部分 decimal part
public boolean isNumber(String s) {
/**
// 先由e或者E分成两部分
// e 或者 E, PartA, E之前是个小数,PartB, E 之后是个整数
// partB: 整数的字符的要求,除了第一位可以是 + -, 别的必须是数字,而且不能只是一个 + -
// partA:
小数的要求,只能第一个字符是 + -,所以我们先检查第一位,之后就不允许出现+-了
dot 最多出现一次
0 - 9 至少出现一次,即不能是 empty number
进入 partB 之前,立刻检查partA是不是合法的
*/
if (s.length() == 0) return false;
Queue<Character> charQueue = new ArrayDeque<>();
for ( char c : s.toCharArray() ) {
charQueue.offer(c);
}
// 先检查符号
if (charQueue.peek() == '+' || charQueue.peek() == '-') {
charQueue.poll();
}
if (charQueue.isEmpty()) return false;
boolean hasDecimal = false;
boolean isEmptyNumber = true;
// 现在我们只关心 . 数字 和 e,别的字符都不允许
// . 最多出现一次
// 数字至少出现一次
// e出现了之后 我们立刻检查前面是不是满足了 数字至少出现一次
while (!charQueue.isEmpty()) {
char c = charQueue.poll();
if (c == '.') {
if (hasDecimal) return false;
hasDecimal = true;
continue;
}
if (c == 'e' || c == 'E') {
if (isEmptyNumber) return false;
return isInteger(charQueue);
}
if (!Character.isDigit(c)) {
return false;
}
isEmptyNumber = false;
}
return !isEmptyNumber;
}
// isInteger 用来检测 partB 是不是一个整数
private boolean isInteger(Queue<Character> charQueue) {
if (charQueue.isEmpty()) return false;
if (charQueue.peek() == '+' || charQueue.peek() == '-') {
charQueue.poll();
}
if (charQueue.isEmpty()) return false;
while (!charQueue.isEmpty()) {
if (!Character.isDigit(charQueue.poll())) {
return false;
}
}
return true;
}
}
Last updated
Was this helpful?