造孽啊,造孽啊,造孽啊。。。。。。。。。。。。。。。。。。。。。
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。
太造孽了,主要是这个题有点扯蛋,我理解的数字字符串和题目不太一样,导致调试了很多次
我自己画的状态转移图
public boolean isNumber(String s) {
if(s == null || s.length() == 0){
return false;
}
//标记是否遇到相应情况
boolean numSeen = false;
boolean dotSeen = false;
boolean eSeen = false;
char[] str = s.trim().toCharArray();
for(int i = 0;i < str.length; i++){
if(str[i] >= '0' && str[i] <= '9'){
numSeen = true;
}else if(str[i] == '.'){
//.之前不能出现.或者e
if(dotSeen || eSeen){
return false;
}
dotSeen = true;
}else if(str[i] == 'e' || str[i] == 'E'){
//e之前不能出现e,必须出现数
if(eSeen || !numSeen){
return false;
}
eSeen = true;
numSeen = false;//重置numSeen,排除123e或者123e+的情况,确保e之后也出现数
}else if(str[i] == '-' || str[i] == '+'){
//+-出现在0位置或者e/E的后面第一个位置才是合法的
if(i != 0 && str[i-1] != 'e' && str[i-1] != 'E'){
return false;
}
}else{//其他不合法字符
return false;
}
}
return numSeen;
}
public static boolean isNumber2(String s){
if(s == null || s.length() == 0){
return false;
}
String str = s.trim();
//整个字符串中是否出现过数字
boolean haveNumber = false;
//.出现在数字前面则后面不能有e
char isDot = 0;
boolean isPreDot = false;
Map<Integer , Map<Character , Integer>> state = new HashMap<>();
//状态0跳转到下一状态
Map<Character , Integer> t0 = new HashMap<>(){{
put('s' , 1); //如果是符号位则跳转到状态 1
put('d' , 2);//如果是数字则跳转到状态 2
put('o' , 3);//如果是小数点则跳转到状态3
}};
//状态1跳转到下一状态
Map<Character , Integer> t1 = new HashMap<>(){{
put('d' , 2);//如果是数字则跳转到状态2
put('o' , 3);//如果是小数点则跳转到状态3
}};
//状态2跳转到下一状态
Map<Character , Integer> t2 = new HashMap<>(){{
put('d' , 2);//如果是数字则跳回自身
put('o' , 3);//如果是点则跳转到状态3
put('e' , 5);//如果是e则跳转到状态5
}};
//状态3跳转到下一状态
Map<Character , Integer> t3 = new HashMap<>(){{
put('d' , 4);//如果是数字则跳转到状态4
put('e' , 5);//如果是e则跳转到状态5
}};
//状态4跳转到下一状态
Map<Character , Integer> t4 = new HashMap<>(){{
put('d' , 4);//如果是数字则跳转到自身
put('e' , 5);//如果是e则跳转到状态5
}};
//状态5跳转到下一状态
Map<Character , Integer> t5 = new HashMap<>(){{
put('s' , 6);//如果是符号位则跳转到状态6
put('d' , 7);//如果是数字则跳转到h状态7
}};
//状态6跳转到下一状态
Map<Character , Integer> t6 = new HashMap<>(){{
put('d' , 7);//如果是数字则跳转到状态7
}};
//状态7
Map<Character , Integer> t7 = new HashMap<>(){{
put('d' , 7);//如果是数字则跳回自身
}};
//加入状态集
state.put(0 , t0);
state.put(1 , t1);
state.put(2 , t2);
state.put(3 , t3);
state.put(4 , t4);
state.put(5 , t5);
state.put(6 , t6);
state.put(7 , t7);
int stateNum = 0;
char key = 0;
int i = 0;
for(i = 0 ; i < str.length() ; i++){
if(str.charAt(i) == '-' || str.charAt(i) == '+'){
key = 's';
}else if(str.charAt(i) <= '9' && str.charAt(i) >= '0'){
key = 'd';
//数字先出现
if(isDot == 0){
isDot = 'd';
}
haveNumber = true;
}else if(str.charAt(i) == '.'){
key = 'o';
//点先出现
if(isDot == 0){
isDot = 'o';
isPreDot = true;
}
}else if(str.charAt(i) == 'e' || str.charAt(i) == 'E'){
key = 'e';
}
if(state.get(stateNum).get(key) == null){
break;
}
//预防 [+、-].e 这样的格式,太扯淡了
if(key == 'e' && str.charAt(i - 1) == '.' && isPreDot){
break;
}
//获取下一状态
stateNum = state.get(stateNum).get(key);
//重置key
key = 0;
}
//只有状态 2、3、4和7最后是合法的 还需要遍历完
return (stateNum == 2 || stateNum == 3 ||stateNum == 4 || stateNum == 7) && i == str.length() && haveNumber;
}
主要思路就是想想怎么样构成一个数字字符串才是合法的,情况很多
其实就是逻辑判断。状态转移只能从左往右不能右往左
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof