题目:
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
test(1, "123", true);
test(2, " 123 ", true);
test(3, "0", true);
test(4, "0123", true); //Cannot agree
test(5, "00", true); //Cannot agree
test(6, "-10", true);
test(7, "-0", true);
test(8, "123.5", true);
test(9, "123.000000", true);
test(10, "-500.777", true);
test(11, "0.0000001", true);
test(12, "0.00000", true);
test(13, "0.", true); //Cannot be more disagree!!!
test(14, "00.5", true); //Strongly cannot agree
test(15, "123e1", true);
test(16, "1.23e10", true);
test(17, "0.5e-10", true);
test(18, "1.0e4.5", false);
test(19, "0.5e04", true);
test(20, "12 3", false);
test(21, "1a3", false);
test(22, "", false);
test(23, " ", false);
test(24, null, false);
test(25, ".1", true); //Ok, if you say so
test(26, ".", false);
test(27, "2e0", true); //Really?!
test(28, "+.8", true);
test(29, " 005047e+6", true); //Damn = =|||
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
算法解析:
There are 5 kind of inputs in my DFA:
digit : number 0-9 for
+,- : operator + or -(negative or positive)
exp: e
dot: .
other: you can return false Immediately
4 final States in my DFA transition diagram : s2, s6, s7, s8
If the state change to final state at last, return true
s2 can accept digits only : +1 -23432 123 and etc
s5 can accept exp expression: +2.4e+12 3e9 and etc
s6 can accept decimals end with dot: 1. -42. and etc
(careful, what if there exist only one dot "."
**** I use a variable flag judging weather there existing numbers. cause 0. and .0 is valid and . is invalid ****
)
s7 can accept decimals: +12.23, 87., 132
It is clear how DFA works in my pictures. We just need to handle the inputs, and update the state according to DFA
如上图,从 0 开始总共有 9 个状态,橙色代表可接受状态,也就是表示此时是合法数字。总共有四大类输入,数字,小数点,e 和 正负号。我们只需要将这个图实现就够了
JAVA代码:
public boolean isNumber(String s) {
int state = 0;
s = s.trim();//去除头尾的空格
//遍历所有字符,当做输入
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
//输入正负号
case '+':
case '-':
if (state == 0) {
state = 1;
} else if (state == 4) {
state = 6;
} else {
return false;
}
break;
//输入数字
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
//根据当前状态去跳转
switch (state) {
case 0:
case 1:
case 2:
state = 2;
break;
case 3:
state = 3;
break;
case 4:
case 5:
case 6:
state = 5;
break;
case 7:
state = 8;
break;
case 8:
state = 8;
break;
default:
return false;
}
break;
//小数点
case '.':
switch (state) {
case 0:
case 1:
state = 7;
break;
case 2:
state = 3;
break;
default:
return false;
}
break;
//e
case 'e':
switch (state) {
case 2:
case 3:
case 8:
state = 4;
break;
default:
return false;
}
break;
default:
return false;
}
}
//橙色部分的状态代表合法数字
return state == 2 || state == 3 || state == 5 || state == 8;
}
C++代码:
class Solution {
public:
bool isNumber(string s) {
if(s.empty())
return false;
s.erase(0,s.find_first_not_of(" "));
s.erase(s.find_last_not_of(" ") + 1);
int state = 0;
for(int i = 0; i < s.length(); i++)
{
switch(s[i])
{
case'+':
case'-':
if(state == 0)
{
state = 1;
}
else if(state == 4)
{
state = 6;
}
else
{
return false;
}
break;
case'0':
case'1':
case'2':
case'3':
case'4':
case'5':
case'6':
case'7':
case'8':
case'9':
if(state == 0 || state == 1 || state == 2)
{
state = 2;
}
else if(state == 3)
{
state = 3;
}
else if(state == 4 || state == 5 || state == 6)
{
state = 5;
}
else if(state == 7 || state == 8)
{
state = 8;
}
else
{
return false;
}
break;
case'.':
if(state == 0 || state == 1)
{
state = 7;
}
else if(state == 2)
{
state = 3;
}
else{
return false;
}
break;
case'e':
if(state == 2|| state == 3|| state == 8)
{
state = 4;
}
else
{
return false;
}
break;
default:
return false;
}
}
return (state == 2 ) || (state == 3 ) || (state == 5 ) || (state == 8 );
}
};