题目链接:力扣
解题思路:从前往后挨个进行有效判断,注意其中e或E和小数点只能出现一次,具体算法如下:
- 初始变量:
- i =0:遍历指针
- dot=false:标记小数点是否已经出现
- E = false:标记E是否已经出现
- 如果首个字符是符号,则去掉符号位,令i++
- 遍历字符串s:
- 如果当前字符是小数点:
- 如果小数点已经出现过了,返回false,否则令dot=true
- 如果e或者E已经出现了,返回false,因为e或E后面只能为整数
- 如果小数点后面没有数字,则小数点前面必须有一个数字,否则返回false(小数格式1的要求)
- 如果小数点前面有数字:
- 如果小数点后面是e或E或0-9或者空,continue(小数格式2和3的要求)
- 如果小数点前面没有数字,则小数点后面必须是0-9,也就是小数点后面不能是e或E或空,(因为小数要么以数字开头,要么小数点开头后面加数字),否则返回false(有效数字组成部分1和2的要求)
- 否则,如果当前字符是e或E:
- 如果e或E已经出现过了或则e后面没有数字,返回false(有效数字组成部分2的要求)
- e或E前面必须有一个整数或者小数,所以e前面必须为一个数字或者小数点,否则返回false
- e或E后面的整数可以带符号,也可以不带符号
- 如果带符号,符号后面没有数字了,返回false
- 如果符号后面有数字,令i++,消耗掉这个符号
- 否则,如果不是数字,直接返回false
- 如果当前字符是小数点:
AC代码:
class Solution {
public static boolean isNumber(String s) {
int i = 0;
//去掉刚开始的符号位
if (s.charAt(i) == '+' || s.charAt(i) == '-') {
i++;
if (s.length() == 1) {
return false;
}
}
//标记 '.' 是否出现,点只能出现一次
boolean dot = false;
//标记E或e是否出现,也只能出现一次
boolean E = false;
for (; i < s.length(); i++) {
if (s.charAt(i) == '.' && !dot) {//如果是 '.',并且 '.' 还没出现过
dot = true;
if (E) {//因为e后面只能是整数,当在e后面出现 '.' 直接返回false
return false;
}
//如果小数点后面没有数字,则小数点前面必须有一个数字,否则返回false
if (i + 1 >= s.length() && (i - 1 < 0 || s.charAt(i - 1) < '0' || s.charAt(i - 1) > '9')) {
return false;
}
//小数点前面有数字
if (i - 1 >= 0 && s.charAt(i - 1) >= '0' && s.charAt(i - 1) <= '9') {
//小数点后面可以是 e或E或 0-9或""
if (i + 1 >= s.length() || s.charAt(i + 1) == 'e' || s.charAt(i + 1) == 'E' || s.charAt(i + 1) >= '0' && s.charAt(i + 1) <= '9') {
continue;
}
}
//小数点前面没有数字,则小数点后面必须是0~9之间的一个数,否则返回false
if (i + 1 >= s.length() || s.charAt(i + 1) < '0' || s.charAt(i + 1) > '9') {
return false;
}
} else if (s.charAt(i) == '.' && dot) {//小数点只能出现一次,再次出现返回false,不过不加这个判断也能通过测试
return false;
} else if (s.charAt(i) == 'e' || s.charAt(i) == 'E') {//当前字符是e或E
//E或e已经出现了,或者e后面没有整数,返回false
if (E || i + 1 >= s.length()) {
return false;
}
E = true;
//e前面必须有整数或者小数,所以e前面必须为一个数字或者是小数点 否则返回false
//因为已经做过判断的前面的字符只会包含+,-,0-9和小数点,所以只需要排除+或者-就可以了
if (i - 1 < 0 || s.charAt(i - 1) == '+' || s.charAt(i - 1) == '-') {
return false;
}
//e后面的整数可以带符号,也可以不带符号,如果带符号,直接跳过符号位
if ((s.charAt(i + 1) == '+' || s.charAt(i + 1) == '-')) {
if (i + 2 >= s.length()) {//符号位后面没有数字了,返回false
return false;
}
i++;//跳过符号位
}
} else if (s.charAt(i) > '9' || s.charAt(i) < '0') {//不是数字,直接返回false
return false;
}
}
return true;
}
}
解法二:正则表达式
AC代码:
class Solution {
public static boolean isNumber(String s) {
return s.matches("^[+-]?((\\d+)|(\\d+\\.\\d*)|(\\d*\\.\\d+))([eE][+-]?\\d+)?$");
}
}