https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/submissions/
分析
这道题主要考察思维全面性和编程能力,如果不能归纳出所有的案例,编码时就要处理各种细节,难以写出高质量的代码。
举几个例子:
3.2e+9
、3.e9
、.e8
、+.3e-2
这些都是有效的数值。乍一看很难理解,但只要我们明白数值由整数部分、小数部分、指数部分组成就容易理解了。
去除字符串首尾的空格后,表示数值的字符串模式为:A[.[B]][e|EA]
。A
是整数部分,代表有符号的整数(即前面可以有+
、-
号);B
代表无符号的整数;[.[B]]
代表小数部分;[e|EA]
代表指数部分。
注意,小数点前后的整数部分不必同时存在,但至少要有一个;指数部分的前后必须都要有数字。
列出这个模式后,就可以实现非常简单有效的编码,而不必使用有限状态自动机。
解法
采用一个index
来遍历字符串,按照字符串的模式,首先判断是否能扫描出A
,接着根据有没有小数点.
来判断是否需要扫描出B
,最后根据有没有e
、E
来判断是否需要扫描出指数部分的A
。如果这3个部分都扫描完了,index
还没有到字符串的尾部,那这就不是合法的数值。
代码
class Solution {
private int index = 0;
public boolean isNumber(String s) {
s = s.trim(); // 去除首尾空格
boolean numeric = scanInteger(s);
if (index < s.length() && s.charAt(index) == '.') { // 出现'.',扫描小数部分
index++;
// 小数部分前后只要有一个整数部分就可以
numeric = scanUnsignedInteger(s) || numeric;
}
if (index < s.length() && (s.charAt(index) == 'e' || s.charAt(index) == 'E')) {
index++;
// 指数部分前后都必须有整数部分
numeric = scanInteger(s) && numeric;
}
return numeric && index == s.length();
}
private boolean scanUnsignedInteger(String s) {
if (index == s.length() || !Character.isDigit(s.charAt(index))) return false;
while (index < s.length() && Character.isDigit(s.charAt(index))) index++;
return true;
}
private boolean scanInteger(String s) {
if (index == s.length()) return false;
if (s.charAt(index) == '+' || s.charAt(index) == '-') index++;
return scanUnsignedInteger(s);
}
}