目录
题目
请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。
数值(按顺序)可以分成以下几个部分:
若干空格
一个 小数 或者 整数
(可选)一个 'e' 或 'E' ,后面跟着一个 整数
若干空格
小数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
下述格式之一:
至少一位数字,后面跟着一个点 '.'
至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
一个点 '.' ,后面跟着至少一位数字
整数(按顺序)可以分成以下几个部分:
(可选)一个符号字符('+' 或 '-')
至少一位数字
部分数值列举如下:
["+100", "5e2", "-123", "3.1416", "-1E-16", "0123"]
部分非数值列举如下:
["12e", "1a3.14", "1.2.3", "+-5", "12e+5.4"]
示例 1:
输入:s = "0"
输出:true
示例 2:
输入:s = "e"
输出:false
示例 3:
输入:s = "."
输出:false
示例 4:
输入:s = " .1 "
输出:true
示例 5:
输入:s = " .1. "
输出:false
示例 6:
输入:s = " 6+1 "
输出:false
提示:
1 <= s.length <= 20
s 仅含英文字母(大写和小写),数字(0-9),加号 '+' ,减号 '-' ,空格 ' ' 或者点 '.' 。
解题思路
第一步:预处理,删除掉字符串前后空格。纯空格返回false
第二步:遍历字符串,根据字符进行判断,如果满足条件则继续循环,不满足则中断,return false
根据字符判断
满足以下则继续循环,不满足则return false
1.符号位:后跟数字或小数点,前一位为数字或没有前一位
2.数字:任何情况均满足,无需判断
3.小数点:小数点之前没出现过,e或E之前没出现过,前一位为数字或后一位为数字
4.e或E:非字符串首位,e或E之前没出现过,后跟符号位或数字
5.其他输入:return false
时间复杂度O(n) 空间复杂度O(1)
代码
public boolean isNumber(String s) {
//预处理:删除掉数值前后空格
int indexBefore = 0;
int indexAfter = s.length() - 1;
while (indexAfter >= 0 && s.charAt(indexAfter) == ' ') {
indexAfter--;
}
//当字符串只有空格时
if (indexAfter == -1) {
return false;
}
while (indexBefore < s.length() && s.charAt(indexBefore) == ' ') {
indexBefore++;
}
s = s.substring(indexBefore, indexAfter + 1);
System.out.println(s);
//--------判断是否为数值---------
//可为小数标识或是没有e标识(e或E之后不能有小数)
boolean canXiaoshu = true;
//小数点已经出现了吗?
boolean point=false;
for (int i = 0; i < s.length(); i++) {
CharType c = toCharType(s.charAt(i));
//字符为符号+、-
if (c == CharType.CHAR_SIGN) {
//不满足以下四种情况,即中断(不限制前一位会出现6+1错误)
//1.后一位为数字且是字符串首位
//2.后一位为.且是字符串首位
//3.后一位为数字且前一位为e或E
//4.后一位为.且前一位为e或E
if (!(i < s.length() - 1 && (toCharType(s.charAt(i+1))==CharType.CHAR_NUMBER
|| toCharType(s.charAt(i+1)) == CharType.CHAR_POINT)
&&(i==0||(i>0&&toCharType(s.charAt(i-1))==CharType.CHAR_EXP))
)) {
return false;
}
}
//字符是数字,任何情况下都对
else if (c==CharType.CHAR_NUMBER) {
}
//字符是.
else if (c == CharType.CHAR_POINT) {
//不满足以下两种情况,即中断(不限制点是否出现过会出现.1.错误)
//1.e没出现过且点.没出现过且前一位为数字
//2.e没出现过且点.没出现过且后一位为数字
if (!(canXiaoshu && !point &&
((i > 0 && toCharType(s.charAt(i-1))==CharType.CHAR_NUMBER)
|| (i < s.length() - 1 && toCharType(s.charAt(i+1))==CharType.CHAR_NUMBER)
)
)
) {
return false;
}else {
//设置点已经出现,限制小数
point=true;
}
}
//字符是e或E
else if (c == CharType.CHAR_EXP) {
//不满足以下两种情况,即中断
//非字符串首位,e没出现过,后一位为符号位(+或-)
//非字符串首位,e没出现过,后一位为数字
if (!(canXiaoshu && i > 0 && i < s.length() - 1
&& (toCharType(s.charAt(i+1))==CharType.CHAR_NUMBER
|| toCharType(s.charAt(i+1))==CharType.CHAR_SIGN
)
)
) {
return false;
} else {
//设置e已经出现,限制小数
canXiaoshu = false;
}
} else {
return false;
}
}
return true;
}
enum CharType {
CHAR_NUMBER,//数字
CHAR_EXP,//e/E
CHAR_POINT,//.
CHAR_SIGN,//+/-
CHAR_ILLEGAL//其他非法输入
}
public CharType toCharType(char ch) {
if (ch >= '0' && ch <= '9') {
return CharType.CHAR_NUMBER;
} else if (ch == 'e' || ch == 'E') {
return CharType.CHAR_EXP;
} else if (ch == '.') {
return CharType.CHAR_POINT;
} else if (ch == '+' || ch == '-') {
return CharType.CHAR_SIGN;
} else {
return CharType.CHAR_ILLEGAL;
}
}