題目:
Validate if a given string is numeric.
Some examples:"0"
=> true
" 0.1 "
=> true
"abc"
=> false
"1 a"
=> false
"2e10"
=> true
Note: It is intended for the problem statement to be ambiguous. You should gather all requirements up front before implementing one.
思路:這題主要是在於輸入形式的多樣性,要進行周全的判斷,採用一些標識符是這題的解題的一大思路。
Java版本:
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;
}
思路是設置四個標識符 pointSeen = false,eSeen = false,numberSeen = false,numberAfterE = true,然後依次對字符串裏的字符進行判斷,並隨之更改標識符的狀態。
Another Java 版本:
public class Solution {
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';
}
}
Python版本:
class Solution(object):
def isNumber(self, s):
"""
:type s: str
:rtype: bool
"""
#define a DFA
state = [{},
{'blank': 1, 'sign': 2, 'digit':3, '.':4},
{'digit':3, '.':4},
{'digit':3, '.':5, 'e':6, 'blank':9},
{'digit':5},
{'digit':5, 'e':6, 'blank':9},
{'sign':7, 'digit':8},
{'digit':8},
{'digit':8, 'blank':9},
{'blank':9}]
currentState = 1
for c in s:
if c >= '0' and c <= '9':
c = 'digit'
if c == ' ':
c = 'blank'
if c in ['+', '-']:
c = 'sign'
if c not in state[currentState].keys():
return False
currentState = state[currentState][c]
if currentState not in [3,5,8,9]:
return False
return True
這裏我們構造一個DFA(確定性有限狀態機),把字符串中各個組成的元素全提出到DFA中,然後,直接把s中的字符一一進行提取,並在DFA中進行判斷歸類。
C++版本:
class Solution {
public:
bool isNumber(string str) {
int state=0, flag=0; // flag to judge the special case "."
while(str[0]==' ') str.erase(0,1);//delete the prefix whitespace
while(str[str.length()-1]==' ') str.erase(str.length()-1, 1);//delete the suffix whitespace
for(int i=0; i<str.length(); i++){
if('0'<=str[i] && str[i]<='9'){
flag=1;
if(state<=2) state=2;
else state=(state<=5)?5:7;
}
else if('+'==str[i] || '-'==str[i]){
if(state==0 || state==3) state++;
else return false;
}
else if('.'==str[i]){
if(state<=2) state=6;
else return false;
}
else if('e'==str[i]){
if(flag&&(state==2 || state==6 || state==7)) state=3;
else return false;
}
else return false;
}
return (state==2 || state==5 || (flag&&state==6) || state==7);
}
};
C++這個版本採用到的也是用到DFA這思路。輸入類型有5種,‘+,-’ ,數字 , ‘.’,e,其他。另外採用到了state這個標識符有着8種狀態,是本思路的一大亮點。