题目:请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 'e' 或 'E' ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
一个点 '.' ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
至少一位数字
解法:有限状态自动机,确定初始状态、接受状态
思路:
挖掘所有的状态的技巧:用「当前处理到字符串的哪个部分」当作状态的表述
所有的状态:
0 起始的空格
1 符号位
2 整数部分
3 左侧有整数的小数点
4 左侧无整数的小数点(根据前面的第二条额外规则,需要对左侧有无整数的两种小数点做区分)
5 小数部分
6 字符 e/E
7 指数部分的符号位
8 指数部分的整数部分
9 末尾的空格
代码:
package offer.q20;
import java.util.HashMap;
import java.util.Map;
class A1 {
public static boolean isNumber(String s) {
Map[] states = {
new HashMap<Character,Integer>() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, // 0
new HashMap<Character,Integer>() {{ put('d', 2); put('.', 4); }}, // 1
new HashMap<Character,Integer>() {{ put('d', 2); put('.', 3); put('e', 6); put(' ', 9); }}, // 2
new HashMap<Character,Integer>() {{ put('d', 5); put('e', 6); put(' ', 9); }}, // 3
new HashMap<Character,Integer>() {{ put('d', 5); }}, // 4
new HashMap<Character,Integer>() {{ put('d', 5); put('e', 6); put(' ', 9);}}, // 5
new HashMap<Character,Integer>() {{ put('s', 7); put('d', 8);}}, // 6
new HashMap<Character,Integer>() {{ put('d', 8); }}, // 7
new HashMap<Character,Integer>() {{ put('d', 8); put(' ', 9);}}, // 8
new HashMap<Character,Integer>() {{ put(' ', 9); }} // 9
};
int p = 0;
char t;
for(char c : s.toCharArray()) {
if(c >= '0' && c <= '9') t = 'd';
else if(c == '+' || c == '-') t = 's';
else if(c == 'e' || c == 'E') t = 'e';
else if(c == '.' || c == ' ') t = c;
else t = '?';
if(!states[p].containsKey(t)) return false;
p = (int)states[p].get(t);
}
return p == 2 || p == 3 || p == 5 || p == 8 || p == 9;
}
public static void main(String[] args) {
System.out.println(isNumber(" .1 "));
}
}
思路2:遍历字符串s,根据之前‘数字’,‘.’,‘E/e’的状态和当前遇到的字符来判断是否符合要求
代码:
package offer.q20;
public class A2 {
public static boolean isNumber(String s) {
if(s == null || s.length() == 0) return false;
boolean isNum = false, isDot = false, ise_or_E = false; // 状态
char[] str = s.trim().toCharArray();
for(int i=0; i<str.length; i++) {
if(str[i] >= '0' && str[i] <= '9') isNum = true; // 数字
else if(str[i] == '.') { // 遇到小数点
if(isDot || ise_or_E) return false; // 小数点之前可以没有整数,但是不能重复出现小数点、或出现‘e’、'E'
isDot = true; // 标记已经遇到小数点
}
else if(str[i] == 'e' || str[i] == 'E') { // 遇到‘e’或'E'
if(!isNum || ise_or_E) return false; // ‘e’或'E'前面必须有整数,且前面不能重复出现‘e’或'E'
ise_or_E = true; // 标记已经遇到‘e’或'E'
isNum = false; // 重置isNum,因为‘e’或'E'之后也必须接上整数,防止出现 123e或者123e+的非法情况
}
else if(str[i] == '-' ||str[i] == '+') {
if(i!=0 && str[i-1] != 'e' && str[i-1] != 'E') return false; // 正负号只可能出现在第一个位置,或者出现在‘e’或'E'的后面一个位置
}
else return false; // 其它情况均为不合法字符
}
return isNum;
}
public static void main(String[] args) {
System.out.println(isNumber(" .1 "));
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。