[Leetcode] Valid Number
Question:
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.
--------------------------
Solution 1:
利用现有库,String.replaceAll(),关于的正则表达式问题可以参看前一篇博客。
1 public class Solution { 2 public boolean isNumber(String s) { 3 s=s.trim(); 4 s=s.replaceAll("e|E", "/"); 5 s=s.replaceAll("[a-zA-Z]", "x"); 6 s=s.replaceAll("/", "e"); 7 8 try { 9 Double.parseDouble(s); 10 } catch (Exception e) { 11 // TODO: handle exception 12 13 return false; 14 } 15 16 return true; 17 } 18 } 19
-------------------
Solution2:
Finite-state Machine solution(有限状态机)。
代码转自:https://github.com/AnnieKim/LeetCode/blob/master/ValidNumber.h
1 class Solution { 2 public: 3 bool isNumber(const char *s) { 4 enum InputType {INVALID, SPACE, SIGN, DIGIT, DOT, EXPONENT}; 5 int transitionTable[][SPACEEND] = 6 { /* 0 1 2 3 4 5 */ 7 0, 1, 2, 3, 4, 0, // 0: INVALID 8 0, 1, 2, 3, 4, 0, // 1: SPACE 9 0, 0, 0, 3, 4, 0, // 2: SIGN 10 0, 6, 0, 3, 7, 5, // 3: DIGIT 11 0, 0, 0, 7, 0, 0, // 4: DOT 12 0, 0, 2, 8, 0, 0, // 5: EXPONENT 13 0, 6, 0, 0, 0, 0, // 6: END WITH SPACE 14 0, 6, 0, 7, 0, 5, // 7: DOT AND DIGIT 15 0, 6, 0, 8, 0, 0, // 8: END WITH SPACE OR DIGIT 16 }; 17 18 InputType last = INVALID; 19 while (*s != '\0') 20 { 21 InputType state = INVALID; 22 if (*s == ' ') 23 state = SPACE; 24 else if (isdigit(*s)) 25 state = DIGIT; 26 else if (*s == '+' || *s == '-') 27 state = SIGN; 28 else if (*s == 'e') 29 state = EXPONENT; 30 else if (*s == '.') 31 state = DOT; 32 last = (InputType) transitionTable[last][state]; 33 if (last == INVALID) return false; 34 s++; 35 } 36 bool validFinal[] = {0, 0, 0, 1, 0, 0, 1, 1, 1}; 37 return validFinal[last]; 38 } 39 };
我用JAVA改写的:
1 public class Solution { 2 public boolean isNumber(String s) { 3 int[][] transitionTable={ 4 /* 0 1 2 3 4 5 */ 5 {0, 1, 2, 3, 4, 0}, // 0: INVALID 6 {0, 1, 2, 3, 4, 0}, // 1: SPACE 7 {0, 0, 0, 3, 4, 0}, // 2: SIGN 8 {0, 6, 0, 3, 7, 5}, // 3: DIGIT 9 {0, 0, 0, 7, 0, 0}, // 4: DOT 10 {0, 0, 2, 8, 0, 0}, // 5: EXPONENT 11 {0, 6, 0, 0, 0, 0}, // 6: END WITH SPACE 12 {0, 6, 0, 7, 0, 5}, // 7: DOT AND DIGIT 13 {0, 6, 0, 8, 0, 0}, // 8: END WITH SPACE OR DIGIT 14 }; 15 int last=0; //invalid 16 for(int i=0;i<s.length();i++){ 17 int state=0; //invalid 18 if(s.charAt(i)==' '){ 19 state=1; //space 20 }else if(Character.isDigit(s.charAt(i))){ 21 state=3; //digit 22 }else if(s.charAt(i)=='+'||s.charAt(i)=='-'){ 23 state=2; //SIGN 24 }else if(s.charAt(i)=='.'){ 25 state=4; //DOT 26 }else if(s.charAt(i)=='e'||s.charAt(i)=='E'){ 27 state=5; //EXPONENT 28 } 29 last=transitionTable[last][state]; 30 if(last==0) return false; 31 } 32 if(last==3||last==6||last==7||last==8) //最后结束状态为3,6,7,8时表示该string确实是一个number 33 return true; 34 else 35 return false; 36 37 } 38 }
--------------------------------------------------------------
其实很想像AnnieKim一样用enum的。。。但是自己enum太不熟了。
public static void main(String[] args) { // TODO Auto-generated method stub Main so = new Main(); InputType a = InputType.SIGN; System.out.println(a.ordinal()); //2 } public enum InputType { INVALID, SPACE, SIGN, DIGIT, DOT, EXPONENT }
通过ordinal函数得到该数的序列号。
但是想要将int值如2转换成InputType的SIGN,要自己写个函数来实现。