19、表示数值的字符串(20、Medium)
1)题目要求
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、“5e2”、"-123"、“3.1416”、"-1E-16"、“0123"都表示数值,但"12e”、“1a3.14”、“1.2.3”、"±5"及"12e+5.4"都不是。
2)我的解法
1、利用正则表达式
class Solution {
public boolean isNumber(String s) {
String s1=s.trim();
return s1.matches("(\\+|\\-)?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))((E|e)(\\+|\\-)?\\d+)?");
}
}
2、一点一点试出来的,太恶心了
class Solution {
public boolean isNumber(String s) {
String s1=s.trim();
int i=0;
if(s1.length()==0)return false;
if(s1.charAt(0)=='+'||s1.charAt(0)=='-')i++;
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
i++;
}
if(i<s1.length()&&s1.charAt(i)=='.'){
i++;
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
i++;
}
if(s1.charAt(i-1)=='.'&&(i<2||s1.charAt(i-2)=='+'||s1.charAt(i-2)=='-'))return false;
}
if(i>0&&s1.charAt(i-1)!='+'&&s1.charAt(i-1)!='-'&&i<s1.length()&&(s1.charAt(i)=='e'||s1.charAt(i)=='E')){
i++;
if(i<s1.length()&&(s1.charAt(i)=='+'||s1.charAt(i)=='-'))i++;
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
i++;
}
}
if(i==s1.length()&&s1.charAt(s1.length()-1)!='E'&&s1.charAt(s1.length()-1)!='e'
&&s1.charAt(s1.length()-1)!='+'&&s1.charAt(s1.length()-1)!='-')return true;
else return false;
}
}
3)其他解法
1、
(可以在2、3之间加一个小数点状态,便于理解)
class Solution {
public boolean isNumber(String s) {
Map[] states = {//理解为邻接矩阵
new HashMap<>() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }}, // 0.
new HashMap<>() {{ put('d', 2); put('.', 4); }}, // 1.
new HashMap<>() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }}, // 2.
new HashMap<>() {{ put('d', 3); put('e', 5); put(' ', 8); }}, // 3.
new HashMap<>() {{ put('d', 3); }}, // 4.
new HashMap<>() {{ put('s', 6); put('d', 7); }}, // 5.
new HashMap<>() {{ put('d', 7); }}, // 6.
new HashMap<>() {{ put('d', 7); put(' ', 8); }}, // 7.
new HashMap<>() {{ put(' ', 8); }} // 8.
};
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 == 7 || p == 8;
}
}
作者:jyd
链接:link
来源:力扣(LeetCode)
2、
class Solution {
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;
}
}
作者:yangshyu6
链接: link
来源:力扣(LeetCode)
4)自己的优化代码
1、
class Solution {
public boolean isNumber(String s) {
String s1=s.trim();
int i=0;
if(s1.length()==0)return false;
if(s1.charAt(0)=='+'||s1.charAt(0)=='-')i++;//正负号
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){//数字
i++;
}
if(i<s1.length()&&s1.charAt(i)=='.'){//小数点
i++;
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
i++;//小数数字
}
//若小数点前后均无数字则返回false
if(s1.charAt(i-1)=='.'&&(i<2||s1.charAt(i-2)=='+'||s1.charAt(i-2)=='-'))return false;
}
if(i>0&&s1.charAt(i-1)!='+'&&s1.charAt(i-1)!='-'&&i<s1.length()&&(s1.charAt(i)=='e'||s1.charAt(i)=='E')){//e|E
i++;
正负号
if(i<s1.length()&&(s1.charAt(i)=='+'||s1.charAt(i)=='-'))i++;
while(i<s1.length()&&s1.charAt(i)>='0'&&s1.charAt(i)<='9'){
i++;//数字
}
}
if(i==s1.length()&&s1.charAt(s1.length()-1)!='E'&&s1.charAt(s1.length()-1)!='e'
&&s1.charAt(s1.length()-1)!='+'&&s1.charAt(s1.length()-1)!='-')return true;
else return false;
//return s1.matches("(\\+|\\-)?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))((E|e)(\\+|\\-)?\\d+)?");
}
}
2、有穷自动机
class Solution {
public boolean isNumber(String s) {
Map[] state=new Map[]{//相当于邻接表
new HashMap() {{ put(' ', 0); put('s', 1); put('d', 2); put('.', 4); }},
new HashMap() {{ put('d', 2); put('.', 4); }},
new HashMap() {{ put('d', 2); put('.', 3); put('e', 5); put(' ', 8); }},
new HashMap() {{ put('d', 3); put('e', 5); put(' ', 8); }},
new HashMap() {{ put('d', 3); }},
new HashMap() {{ put('s', 6); put('d', 7); }},
new HashMap() {{ put('d', 7); }},
new HashMap() {{ put('d', 7); put(' ', 8); }},
new HashMap() {{ put(' ', 8); }}
};
char zt;
int p=0;
for(char c:s.toCharArray()){
if(c>='0'&&c<='9')zt='d';
else if(c=='+'||c=='-')zt='s';
else if(c=='e'||c=='E')zt='e';
else if(c=='.')zt='.';
else if(c==' ')zt=' ';
else return false;
if(!state[p].containsKey(zt))return false;
p=(int)state[p].get(zt);
}
return p==2||p==3||p==7||p==8;
}
}
5)学到的东西
正则表达式
Map数组,不能加尖括号
HashMap直接初始化:(两个大括号)
new HashMap() {{ put(’ ‘, 0); put(‘s’, 1); put(‘d’, 2); put(’.’, 4); }}
有穷自动机
考虑所有的状态,再把每一个状态的转换关系画出来(一个个画,别着急),再确定合法的结束状态