「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
前言
力扣第六十五题 有效数字 如下所示:
示例 1:
输入: s = "0"
输出: true
示例 2:
输入: s = "e"
输出: false
示例 3:
输入: s = "."
输出: false
示例 4:
输入: s = ".1"
输出: true
一、思路
这一题如果在日常的开发过程中我大概率会使用 正则表达式 来校验某个字符串是不是有效的数字。但考虑到这是一道算法练习题,所以就用别的方式了。
这一题我是使用 穷举 的方式来实现的,其中最值得关心的情况就是 字符串中是否有且仅有一个科学计数法的 e,且 e 的位置不在头或尾部
- 如果含有
e:判断e前面是否为整数或小数,e后面是否为整数 - 如果不含有
e:判断该字符串是否为整数或小数
举个例子
此处就以稍微复杂一点的 str = +.3e-10 作为例子
- 以
e作为标记,将字符串分为+.3和-10 - 易知,
e前面的+.3满足小数的标准 - 易知,
e后面的-10满足整数的标准 - 综上所述,
+.3e-10为一个有效的数字
二、实现
实现代码
代码虽然比较长,但是都有注释,且将公共的地方提出来做成了公用的方法。总体上是比较好理解的,故不作过多解释。
/**
* 复杂情况模拟
*/
public boolean isNumber(String s) {
char[] chars = s.toCharArray();
int ePosition = -1; // e的位置
for (int i=0; i<chars.length; i++) {
// 找有没有 e
char c = chars[i];
if (c == 'e' || c == 'E') {
ePosition = i;
break;
}
}
// 判断e前面部分是否正确
if (ePosition != -1) { // 有科学计数标识
// e 不能在头或尾
if (ePosition == 0 || ePosition == chars.length -1) {
return false;
}
// e的后面不能是一个单独的加号或减号
if (chars.length - ePosition == 2 && (chars[ePosition + 1] == '+' || chars[ePosition + 1] == '-')) {
return false;
}
// e的前面不能是一个单独的加号或减号
if (ePosition == 1 && (chars[0] == '+' || chars[0] == '-')) {
return false;
}
return isDecimalOrInteger(chars, ePosition) && isInteger(chars, true, ePosition + 1, chars.length);
} else {
return isDecimalOrInteger(chars, chars.length);
}
}
/**
* 区间:左开右闭
*/
private boolean isDecimalOrInteger(char[] chars , int end) {
int dotPosition = -1;
// 判断是否有点
for (int i =0; i<end; i++) {
if (chars[i] == '.') {
dotPosition = i;
break;
}
}
// 至少一位数字,后面跟着一个点 '.'
// 至少一位数字,后面跟着一个点 '.' ,后面再跟着至少一位数字
// 一个点 '.' ,后面跟着至少一位数字
if (dotPosition == 0 && end == 1 || (dotPosition == end -1 && (chars[dotPosition-1] < '0' || chars[dotPosition-1] > '9'))) {
return false;
} else if (dotPosition != -1) {
return isInteger(chars, true, 0, dotPosition) && isInteger(chars, false, dotPosition + 1, end);
} else {
return isInteger(chars, true, 0, end);
}
}
/**
* 区间:左开右闭
*/
private boolean isInteger(char[] chars, boolean withSymbol, int start, int end) {
for (int i=start; i<end; i++) {
char c = chars[i];
if (withSymbol && i == start && (c == '-' || c == '+')) {
continue;
}else if (c < '0' || c > '9') {
return false;
}
}
return true;
}
测试代码
public static void main(String[] args) {
String str = "+.3e-10";
boolean flag = new Number65().isNumber(str);
System.out.println(flag);
}
结果
三、总结
用逻辑推理的方式,真的是一直在Debug。我总共提交了快20次,才能够通过所有的测试用例。
后面看了官方的题解,有限状态机是一个更好的实现方式,逻辑也会更清晰!
感谢看到最后,非常荣幸能够帮助到你~♥
如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~