Valid Number
问题:
判断所给的字符串是不是数字。
例子:
“0” -> true
“0.1” -> true
“abc” -> false
面试者可能会问的问题:
Q: 如果字符串中有空格怎么处理?
A: 当决定一个字符串是否是数字时,忽略所有的前缀和后缀空格。
Q: 如果碰到字符中间有空格我是否应该忽略?比如”1 1”
A: 不,只忽略开始和结束空格,”1 1”不是数字。
Q: 如果字符串在数字部分之后包含其他的字符,这个属于有效吗?
A: 不,如果字符串含有不是数字部分(除了空格和小数点),都不属于数字。
Q: 如果有正负号出现在数字前面,这个属于有效吗?
A: 有效,”+1”和”-1”都属于数字。
Q: 是不是只有十进制的数字才算是数字?如果是16进制的数字呢?(0xFF)
A: 只考虑十进制的数字,”0xFF”不是数字。
Q: 我是否要认为指数”1e10”是数字?
A: 不,但是请自己选择接受这样的挑战。(网上习题有这样一道题)
解决方案:
这道问题非常像之前的[8. String to Integer (atoi)],由于很多的边界问题,将问题分成小块,分而治之是非常有帮助的。
一个字符串从左到右可以分成以下几个方面:
s1. 前缀空格 (可能有或没有)
s2. 正负号 (可能有或没有)
s3. 数字
s4. 后缀空格 (可能有或没有)
我们忽略s1,s2,s4,而直接判断s3是否是有效数字。我们意识到一个数字可以是一个整数或者是一个小数。如果是一个整数,非常简单:我们可以判断每一位数位是不是数字,是的话就解决了。
另外一方面,一个小数可以分成以下几部分:
a. 整数部分
b. 小数点
c. 小数部分
整数和小数部分应该只包含数字。例如:”3.64”就有整数部分(3)和小数部分(64)。他们都是可选的,但是他们之间至少有一个需要在。例如,”.”不是一个有效的数字,但是”1.”,”.1”或者”1.0”都是有效的。注意”1.”有效是因为它代表”1.0”。
至此为止,将需求转化为代码已经非常直接了。在下面代码中,在中间几行是处理判断s3是否是数字的逻辑。
public boolean isNumber(String s) {
int i = 0, n = s.length();
while (i < n && Character.isWhitespace(s.charAt(i))) i++;
if (i < n && (s.charAt(i) == '+' || s.charAt(i) == '-')) i++;
boolean isNumeric = false;
while (i < n && Character.isDigit(s.charAt(i))) {
i++;
isNumeric = true;
}
if (i < n && s.charAt(i) == '.') {
i++;
while (i < n && Character.isDigit(s.charAt(i))) {
i++;
isNumeric = true;
}
}
while (i < n && Character.isWhitespace(s.charAt(i))) i++;
return isNumeric && i == n;
}
进一步思考
一个数字可能会包含指数部分,其中有一个”e”字符以及接下去的完整的数字(指数部分)。例如,”1e10”是一个数字。修改代码来兼容这个新需求。
根据上面已经实现的方案能非常容易的扩展。以下是代码:
public boolean isNumber(String s) {
int i = 0, n = s.length();
while (i < n && Character.isWhitespace(s.charAt(i))) i++;
if (i < n && (s.charAt(i) == '+' || s.charAt(i) == '-')) i++;
boolean isNumeric = false;
while (i < n && Character.isDigit(s.charAt(i))) {
i++;
isNumeric = true;
}
if (i < n && s.charAt(i) == '.') {
i++;
while (i < n && Character.isDigit(s.charAt(i))) {
i++;
isNumeric = true;
}
}
// 以下代码块是新增加的内容以兼容指数,如果碰到了'e'
if (isNumeric && i < n && s.charAt(i) == 'e') {
// 继续往前进
i++;
// 将isNumeric设置为false
isNumeric = false;
// 如果当前字符是正负号,则继续向前
if (i < n && (s.charAt(i) == '+' || s.charAt(i) == '-')) i++;
// 剩下的数字每一位都应该是数字
while (i < n && Character.isDigit(s.charAt(i))) {
i++;
isNumeric = true;
}
}
while (i < n && Character.isWhitespace(s.charAt(i))) i++;
return isNumeric && i == n;
}